diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 948ffdc1f7c01..726ca0ce4d776 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -233,6 +233,9 @@ def fillna(self: _T, value=None, method=None, limit=None) -> _T: new_values = self.copy() return new_values + # ------------------------------------------------------------------------ + # Reductions + def _reduce(self, name: str, skipna: bool = True, **kwargs): meth = getattr(self, name, None) if meth: diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index ef8093660b413..b95a7acc19b1f 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -207,8 +207,6 @@ def _from_sequence( return scalars periods = np.asarray(scalars, dtype=object) - if copy: - periods = periods.copy() freq = freq or libperiod.extract_freq(periods) ordinals = libperiod.extract_ordinals(periods, freq) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 17fcd00b7b251..c948291f29aeb 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -120,7 +120,7 @@ class TimedeltaArray(dtl.TimelikeOps): "ceil", ] - # Note: ndim must be defined to ensure NaT.__richcmp(TimedeltaArray) + # Note: ndim must be defined to ensure NaT.__richcmp__(TimedeltaArray) # operates pointwise. def _box_func(self, x) -> Union[Timedelta, NaTType]: @@ -520,7 +520,7 @@ def __mul__(self, other) -> "TimedeltaArray": def __truediv__(self, other): # timedelta / X is well-defined for timedelta-like or numeric X - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) if other is NaT: # specifically timedelta64-NaT @@ -577,7 +577,7 @@ def __truediv__(self, other): @unpack_zerodim_and_defer("__rtruediv__") def __rtruediv__(self, other): # X / timedelta is defined only for timedelta-like X - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) if other is NaT: # specifically timedelta64-NaT @@ -620,7 +620,7 @@ def __rtruediv__(self, other): def __floordiv__(self, other): if is_scalar(other): - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) if other is NaT: # treat this specifically as timedelta-NaT @@ -684,7 +684,7 @@ def __floordiv__(self, other): def __rfloordiv__(self, other): if is_scalar(other): - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) if other is NaT: # treat this specifically as timedelta-NaT @@ -730,21 +730,21 @@ def __rfloordiv__(self, other): @unpack_zerodim_and_defer("__mod__") def __mod__(self, other): # Note: This is a naive implementation, can likely be optimized - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) return self - (self // other) * other @unpack_zerodim_and_defer("__rmod__") def __rmod__(self, other): # Note: This is a naive implementation, can likely be optimized - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) return other - (other // self) * self @unpack_zerodim_and_defer("__divmod__") def __divmod__(self, other): # Note: This is a naive implementation, can likely be optimized - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) res1 = self // other @@ -754,7 +754,7 @@ def __divmod__(self, other): @unpack_zerodim_and_defer("__rdivmod__") def __rdivmod__(self, other): # Note: This is a naive implementation, can likely be optimized - if isinstance(other, (timedelta, np.timedelta64, Tick)): + if isinstance(other, self._recognized_scalars): other = Timedelta(other) res1 = other // self diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 6b64fd6a20e9a..fb0e710921a5f 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -578,7 +578,7 @@ def _convert_list_indexer(self, keyarr): return self.get_indexer(keyarr) @doc(Index._maybe_cast_slice_bound) - def _maybe_cast_slice_bound(self, label, side, kind): + def _maybe_cast_slice_bound(self, label, side: str, kind): if kind == "loc": return label diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index d8fab1283dfdc..7f0dc2426eba7 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -831,7 +831,7 @@ def _should_fallback_to_positional(self) -> bool: # positional in this case return self.dtype.subtype.kind in ["m", "M"] - def _maybe_cast_slice_bound(self, label, side, kind): + def _maybe_cast_slice_bound(self, label, side: str, kind): return getattr(self, side)._maybe_cast_slice_bound(label, side, kind) @Appender(Index._convert_list_indexer.__doc__) diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index facaae3a65f16..546b90249b5ca 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -96,7 +96,7 @@ def _validate_dtype(cls, dtype: Dtype) -> None: # Indexing Methods @doc(Index._maybe_cast_slice_bound) - def _maybe_cast_slice_bound(self, label, side, kind): + def _maybe_cast_slice_bound(self, label, side: str, kind): assert kind in ["loc", "getitem", None] # we will try to coerce to integers diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 302fead8c8b0c..66fd6943de721 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -8,8 +8,6 @@ from pandas.core.dtypes.common import ( TD64NS_DTYPE, - is_float, - is_integer, is_scalar, is_timedelta64_dtype, is_timedelta64_ns_dtype, @@ -246,7 +244,7 @@ def _maybe_cast_slice_bound(self, label, side: str, kind): return lbound else: return lbound + to_offset(parsed.resolution_string) - Timedelta(1, "ns") - elif is_integer(label) or is_float(label): + elif not isinstance(label, self._data._recognized_scalars): self._invalid_indexer("slice", label) return label diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index 1132234ae7f8d..2e32a7572adc7 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -29,6 +29,7 @@ from pandas.core.construction import extract_array if TYPE_CHECKING: + from pandas import MultiIndex from pandas.core.indexes.base import Index _INT64_MAX = np.iinfo(np.int64).max @@ -415,7 +416,9 @@ def nargminmax(values, method: str): return non_nan_idx[func(non_nans)] -def ensure_key_mapped_multiindex(index, key: Callable, level=None): +def _ensure_key_mapped_multiindex( + index: "MultiIndex", key: Callable, level=None +) -> "MultiIndex": """ Returns a new MultiIndex in which key has been applied to all levels specified in level (or all levels if level @@ -441,7 +444,6 @@ def ensure_key_mapped_multiindex(index, key: Callable, level=None): labels : MultiIndex Resulting MultiIndex with modified levels. """ - from pandas.core.indexes.api import MultiIndex if level is not None: if isinstance(level, (str, int)): @@ -460,7 +462,7 @@ def ensure_key_mapped_multiindex(index, key: Callable, level=None): for level in range(index.nlevels) ] - labels = MultiIndex.from_arrays(mapped) + labels = type(index).from_arrays(mapped) return labels @@ -484,7 +486,7 @@ def ensure_key_mapped(values, key: Optional[Callable], levels=None): return values if isinstance(values, ABCMultiIndex): - return ensure_key_mapped_multiindex(values, key, level=levels) + return _ensure_key_mapped_multiindex(values, key, level=levels) result = key(values.copy()) if len(result) != len(values): diff --git a/pandas/tests/groupby/test_apply.py b/pandas/tests/groupby/test_apply.py index f5078930a7b4b..a7c22b4983ed7 100644 --- a/pandas/tests/groupby/test_apply.py +++ b/pandas/tests/groupby/test_apply.py @@ -981,25 +981,6 @@ def test_apply_function_index_return(function): tm.assert_series_equal(result, expected) -def test_apply_function_with_indexing(): - # GH: 33058 - df = DataFrame({"col1": ["A", "A", "A", "B", "B", "B"], "col2": [1, 2, 3, 4, 5, 6]}) - - def fn(x): - x.col2[x.index[-1]] = 0 - return x.col2 - - result = df.groupby(["col1"], as_index=False).apply(fn) - expected = Series( - [1, 2, 0, 4, 5, 0], - index=pd.MultiIndex.from_tuples( - [(0, 0), (0, 1), (0, 2), (1, 3), (1, 4), (1, 5)] - ), - name="col2", - ) - tm.assert_series_equal(result, expected) - - def test_apply_function_with_indexing_return_column(): # GH: 7002 df = DataFrame(