Skip to content

CLN: int slice on Index[float] as positional #58646

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

Merged
merged 1 commit into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doc/source/whatsnew/v0.13.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ Float64Index API change
.. ipython:: python
:okwarning:

s[2:4]
s.loc[2:4]
s.iloc[2:4]

Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ Removal of prior version deprecations/changes
- All arguments except ``name`` in :meth:`Index.rename` are now keyword only (:issue:`56493`)
- All arguments except the first ``path``-like argument in IO writers are now keyword only (:issue:`54229`)
- Changed behavior of :meth:`Series.__getitem__` and :meth:`Series.__setitem__` to always treat integer keys as labels, never as positional, consistent with :class:`DataFrame` behavior (:issue:`50617`)
- Changed 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. This is now treated as *positional* indexing (:issue:`49612`)
- Disallow a callable argument to :meth:`Series.iloc` to return a ``tuple`` (:issue:`53769`)
- Disallow allowing logical operations (``||``, ``&``, ``^``) between pandas objects and dtype-less sequences (e.g. ``list``, ``tuple``); wrap the objects in :class:`Series`, :class:`Index`, or ``np.array`` first instead (:issue:`52264`)
- Disallow automatic casting to object in :class:`Series` logical operations (``&``, ``^``, ``||``) between series with mismatched indexes and dtypes other than ``object`` or ``bool`` (:issue:`52538`)
Expand Down
19 changes: 0 additions & 19 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4003,25 +4003,6 @@ def _convert_slice_indexer(self, key: slice, kind: Literal["loc", "getitem"]):

# TODO(GH#50617): once Series.__[gs]etitem__ is removed we should be able
# to simplify this.
if lib.is_np_dtype(self.dtype, "f"):
# 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)

if kind == "getitem":
# called from the getitem slicers, validate that we are in fact integers
if is_index_slice:
Expand Down
14 changes: 8 additions & 6 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,14 @@ def test_getitem_setitem_boolean_multi(self):
expected.loc[[0, 2], [1]] = 5
tm.assert_frame_equal(df, expected)

def test_getitem_float_label_positional(self):
# GH 53338
index = Index([1.5, 2])
df = DataFrame(range(2), index=index)
result = df[1:2]
expected = DataFrame([1], index=[2.0])
tm.assert_frame_equal(result, expected)

def test_getitem_setitem_float_labels(self):
index = Index([1.5, 2, 3, 4, 5])
df = DataFrame(np.random.default_rng(2).standard_normal((5, 5)), index=index)
Expand All @@ -748,12 +756,6 @@ 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]
tm.assert_frame_equal(result, expected)

# #2727
index = Index([1.0, 2.5, 3.5, 4.5, 5.0])
df = DataFrame(np.random.default_rng(2).standard_normal((5, 5)), index=index)
Expand Down
16 changes: 2 additions & 14 deletions pandas/tests/indexing/test_floats.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,24 +488,12 @@ 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):
result1 = indexer_sl(s)[2:5]
result2 = indexer_sl(s)[2.0:5.0]
result3 = indexer_sl(s)[2.0:5]
result4 = indexer_sl(s)[2.1:5]
tm.assert_series_equal(result1, result2)
tm.assert_series_equal(result1, result3)
tm.assert_series_equal(result1, result4)

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

tm.assert_series_equal(result, expected)
tm.assert_series_equal(result2, result3)
tm.assert_series_equal(result2, result4)

# list selection
result1 = indexer_sl(s)[[0.0, 5, 10]]
Expand Down