diff --git a/doc/source/whatsnew/v1.5.3.rst b/doc/source/whatsnew/v1.5.3.rst index c0df15b67a4a7..0cb8796e3fb5d 100644 --- a/doc/source/whatsnew/v1.5.3.rst +++ b/doc/source/whatsnew/v1.5.3.rst @@ -37,6 +37,7 @@ Bug fixes Other ~~~~~ +- Reverted deprecation (:issue:`45324`) of behavior of :meth:`Series.__getitem__` and :meth:`Series.__setitem__` slicing with an integer :class:`Index`; this will remain positional (:issue:`49612`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 798ea8a61093a..25bbc577ad674 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -3786,9 +3786,7 @@ def __getitem__(self, key): return self._getitem_multilevel(key) # Do we have a slicer (on rows)? if isinstance(key, slice): - indexer = self.index._convert_slice_indexer( - key, kind="getitem", is_frame=True - ) + indexer = self.index._convert_slice_indexer(key, kind="getitem") if isinstance(indexer, np.ndarray): # reachable with DatetimeIndex indexer = lib.maybe_indices_to_slice( @@ -3967,7 +3965,7 @@ def __setitem__(self, key, value): # see if we can slice the rows if isinstance(key, slice): - slc = self.index._convert_slice_indexer(key, kind="getitem", is_frame=True) + slc = self.index._convert_slice_indexer(key, kind="getitem") return self._setitem_slice(slc, value) if isinstance(key, DataFrame) or getattr(key, "ndim", None) == 2: diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 53491d12e7172..77cefc456dd07 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -123,7 +123,6 @@ ABCDatetimeIndex, ABCMultiIndex, ABCPeriodIndex, - ABCRangeIndex, ABCSeries, ABCTimedeltaIndex, ) @@ -3846,7 +3845,7 @@ def _validate_positional_slice(self, key: slice) -> None: self._validate_indexer("positional", key.stop, "iloc") self._validate_indexer("positional", key.step, "iloc") - def _convert_slice_indexer(self, key: slice, kind: str_t, is_frame: bool = False): + def _convert_slice_indexer(self, key: slice, kind: str_t): """ Convert a slice indexer. @@ -3857,9 +3856,6 @@ def _convert_slice_indexer(self, key: slice, kind: str_t, is_frame: bool = False ---------- key : label of the slice bound kind : {'loc', 'getitem'} - is_frame : bool, default False - Whether this is a slice called on DataFrame.__getitem__ - as opposed to Series.__getitem__ """ assert kind in ["loc", "getitem"], kind @@ -3882,42 +3878,6 @@ def is_int(v): if kind == "getitem": # called from the getitem slicers, validate that we are in fact integers - if self.is_integer(): - if is_frame: - # unambiguously positional, no deprecation - pass - elif start is None and stop is None: - # label-based vs positional is irrelevant - pass - elif isinstance(self, ABCRangeIndex) and self._range == range( - len(self) - ): - # In this case there is no difference between label-based - # and positional, so nothing will change. - pass - elif ( - self.dtype.kind in ["i", "u"] - and self._is_strictly_monotonic_increasing - and len(self) > 0 - and self[0] == 0 - and self[-1] == len(self) - 1 - ): - # We are range-like, e.g. created with Index(np.arange(N)) - pass - elif not is_index_slice: - # we're going to raise, so don't bother warning, e.g. - # test_integer_positional_indexing - pass - else: - warnings.warn( - "The behavior of `series[i:j]` with an integer-dtype index " - "is deprecated. In a future version, this will be treated " - "as *label-based* indexing, consistent with e.g. `series[i]` " - "lookups. To retain the old behavior, use `series.iloc[i:j]`. " - "To get the future behavior, use `series.loc[i:j]`.", - FutureWarning, - stacklevel=find_stack_level(), - ) if self.is_integer() or is_index_slice: # Note: these checks are redundant if we know is_index_slice self._validate_indexer("slice", key.start, "getitem") diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 997bf7c9a7fb1..762d79a28c720 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -796,7 +796,7 @@ def _index_as_unique(self) -> bool: "cannot handle overlapping indices; use IntervalIndex.get_indexer_non_unique" ) - def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False): + def _convert_slice_indexer(self, key: slice, kind: str): if not (key.step is None or key.step == 1): # GH#31658 if label-based, we require step == 1, # if positional, we disallow float start/stop @@ -808,7 +808,7 @@ def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False): # i.e. this cannot be interpreted as a positional slice raise ValueError(msg) - return super()._convert_slice_indexer(key, kind, is_frame=is_frame) + return super()._convert_slice_indexer(key, kind) @cache_readonly def _should_fallback_to_positional(self) -> bool: diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 7af66f97a8cf7..df353e98fde4a 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -219,7 +219,7 @@ def _should_fallback_to_positional(self) -> bool: return False @doc(Index._convert_slice_indexer) - def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False): + def _convert_slice_indexer(self, key: slice, kind: str): # TODO(2.0): once #45324 deprecation is enforced we should be able # to simplify this. if is_float_dtype(self.dtype): @@ -231,7 +231,7 @@ def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False): # translate to locations return self.slice_indexer(key.start, key.stop, key.step) - return super()._convert_slice_indexer(key, kind=kind, is_frame=is_frame) + return super()._convert_slice_indexer(key, kind=kind) @doc(Index._maybe_cast_slice_bound) def _maybe_cast_slice_bound(self, label, side: str): diff --git a/pandas/tests/extension/base/getitem.py b/pandas/tests/extension/base/getitem.py index e966d4602a02c..cf51d9d693155 100644 --- a/pandas/tests/extension/base/getitem.py +++ b/pandas/tests/extension/base/getitem.py @@ -313,8 +313,7 @@ def test_get(self, data): expected = s.iloc[[2, 3]] self.assert_series_equal(result, expected) - with tm.assert_produces_warning(FutureWarning, match="label-based"): - result = s.get(slice(2)) + result = s.get(slice(2)) expected = s.iloc[[0, 1]] self.assert_series_equal(result, expected) diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index 0480278877398..c07b0e81da12b 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -337,8 +337,7 @@ def test_integer_positional_indexing(self, idx): """ s = Series(range(2, 6), index=range(2, 6)) - with tm.assert_produces_warning(FutureWarning, match="label-based"): - result = s[2:4] + result = s[2:4] expected = s.iloc[2:4] tm.assert_series_equal(result, expected) diff --git a/pandas/tests/series/indexing/test_get.py b/pandas/tests/series/indexing/test_get.py index 1a54796dbeec3..e8034bd4f7160 100644 --- a/pandas/tests/series/indexing/test_get.py +++ b/pandas/tests/series/indexing/test_get.py @@ -167,8 +167,7 @@ def test_get_with_ea(arr): expected = ser.iloc[[2, 3]] tm.assert_series_equal(result, expected) - with tm.assert_produces_warning(FutureWarning, match="label-based"): - result = ser.get(slice(2)) + result = ser.get(slice(2)) expected = ser.iloc[[0, 1]] tm.assert_series_equal(result, expected) diff --git a/pandas/tests/series/indexing/test_getitem.py b/pandas/tests/series/indexing/test_getitem.py index 86fabf0ed0ef2..53c237d2d47bb 100644 --- a/pandas/tests/series/indexing/test_getitem.py +++ b/pandas/tests/series/indexing/test_getitem.py @@ -332,8 +332,7 @@ def test_getitem_slice_bug(self): def test_getitem_slice_integers(self): ser = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16]) - with tm.assert_produces_warning(FutureWarning, match="label-based"): - result = ser[:4] + result = ser[:4] expected = Series(ser.values[:4], index=[2, 4, 6, 8]) tm.assert_series_equal(result, expected) diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index d731aeee1b39b..fa196cf7d3f32 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -220,15 +220,9 @@ def test_setitem_slice(self): def test_setitem_slice_integers(self): ser = Series(np.random.randn(8), index=[2, 4, 6, 8, 10, 12, 14, 16]) - msg = r"In a future version, this will be treated as \*label-based\* indexing" - with tm.assert_produces_warning(FutureWarning, match=msg): - ser[:4] = 0 - with tm.assert_produces_warning( - FutureWarning, match=msg, check_stacklevel=False - ): - assert (ser[:4] == 0).all() - with tm.assert_produces_warning(FutureWarning, match=msg): - assert not (ser[4:] == 0).any() + ser[:4] = 0 + assert (ser[:4] == 0).all() + assert not (ser[4:] == 0).any() def test_setitem_slicestep(self): # caught this bug when writing tests