Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLN: Changed the behavior of Series.__[gs]etitem__ with an integer slice on objects with a floating-dtype index to a positional instead of label-based slicing #58449

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion asv_bench/benchmarks/indexing.py
Expand Up @@ -47,7 +47,7 @@ def time_getitem_scalar(self, index, index_structure):
self.data[800000]

def time_getitem_slice(self, index, index_structure):
self.data[:800000]
self.data.loc[:800000]

def time_getitem_list_like(self, index, index_structure):
self.data[[800000]]
Expand Down
23 changes: 18 additions & 5 deletions doc/source/whatsnew/v0.13.0.rst
Expand Up @@ -342,12 +342,25 @@ Float64Index API change

Slicing is ALWAYS on the values of the index, for ``[],ix,loc`` and ALWAYS positional with ``iloc``

.. ipython:: python
:okwarning:
.. code-block:: ipython

In [1]: s[2:4]
Out[23]:
2.0 1
3.0 2
dtype: int64

In [24]: s.loc[2:4]
Out[24]:
2.0 1
3.0 2
dtype: int64

s[2:4]
s.loc[2:4]
s.iloc[2:4]
In[25]: s.iloc[2:4]
Out[25]:
3.0 2
4.5 3
dtype: int64

In float indexes, slicing using floats are allowed

Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Expand Up @@ -240,6 +240,7 @@ Removal of prior version deprecations/changes
- Removed the "closed" and "unit" keywords in :meth:`TimedeltaIndex.__new__` (:issue:`52628`, :issue:`55499`)
- All arguments in :meth:`Index.sort_values` are now keyword only (:issue:`56493`)
- All arguments in :meth:`Series.to_dict` are now keyword only (:issue:`56493`)
- Changed the behavior of :meth:`Series.__getitem__`, :meth:`Series.__setitem__`, :meth:`DataFrame.__getitem__`, :meth:`DataFrame.__setitem__` with an integer slice on objects with a floating-dtype index from label-based to a *positional* indexing (:issue:`58449`)
- Changed the default value of ``observed`` in :meth:`DataFrame.groupby` and :meth:`Series.groupby` to ``True`` (:issue:`51811`)
- Enforce deprecation in :func:`testing.assert_series_equal` and :func:`testing.assert_frame_equal` with object dtype and mismatched null-like values, which are now considered not-equal (:issue:`18463`)
- Enforced deprecation ``all`` and ``any`` reductions with ``datetime64``, :class:`DatetimeTZDtype`, and :class:`PeriodDtype` dtypes (:issue:`58029`)
Expand Down
15 changes: 1 addition & 14 deletions pandas/core/indexes/base.py
Expand Up @@ -3842,20 +3842,7 @@ def _convert_slice_indexer(self, key: slice, kind: Literal["loc", "getitem"]):
# We always treat __getitem__ slicing as label-based
# translate to locations
if kind == "getitem" and is_index_slice and not start == stop and step != 0:
# exclude step=0 from the warning because it will raise anyway
# start/stop both None e.g. [:] or [::-1] won't change.
# exclude start==stop since it will be empty either way, or
# will be [:] or [::-1] which won't change
warnings.warn(
# GH#49612
"The behavior of obj[i:j] with a float-dtype index is "
"deprecated. In a future version, this will be treated as "
"positional instead of label-based. For label-based slicing, "
"use obj.loc[i:j] instead",
FutureWarning,
stacklevel=find_stack_level(),
)
return self.slice_indexer(start, stop, step)
self.loc[start:stop] # type: ignore[attr-defined]

if kind == "getitem":
# called from the getitem slicers, validate that we are in fact integers
Expand Down
5 changes: 1 addition & 4 deletions pandas/tests/frame/indexing/test_indexing.py
Expand Up @@ -748,10 +748,7 @@ def test_getitem_setitem_float_labels(self):
expected = df.iloc[0:2]
tm.assert_frame_equal(result, expected)

expected = df.iloc[0:2]
msg = r"The behavior of obj\[i:j\] with a float-dtype index"
with tm.assert_produces_warning(FutureWarning, match=msg):
result = df[1:2]
result = df.loc[1:2]
tm.assert_frame_equal(result, expected)

# #2727
Expand Down
12 changes: 7 additions & 5 deletions pandas/tests/indexing/test_floats.py
Expand Up @@ -491,11 +491,11 @@ def test_floating_misc(self, indexer_sl):
for fancy_idx in [[5, 0], np.array([5, 0])]:
tm.assert_series_equal(indexer_sl(s)[fancy_idx], expected)

warn = FutureWarning if indexer_sl is tm.setitem else None
msg = r"The behavior of obj\[i:j\] with a float-dtype index"

# all should return the same as we are slicing 'the same'
with tm.assert_produces_warning(warn, match=msg):

if indexer_sl is tm.setitem:
result1 = indexer_sl(s).loc[2:5]
else:
result1 = indexer_sl(s)[2:5]
result2 = indexer_sl(s)[2.0:5.0]
result3 = indexer_sl(s)[2.0:5]
Expand All @@ -505,7 +505,9 @@ def test_floating_misc(self, indexer_sl):
tm.assert_series_equal(result1, result4)

expected = Series([1, 2], index=[2.5, 5.0])
with tm.assert_produces_warning(warn, match=msg):
if indexer_sl is tm.setitem:
result = indexer_sl(s).loc[2:5]
else:
result = indexer_sl(s)[2:5]

tm.assert_series_equal(result, expected)
Expand Down