Skip to content

DEPR: Disallow indexing an Index with a float #49431

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

Closed
wants to merge 1 commit into from
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v2.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ Removal of prior version deprecations/changes
- Enforced :meth:`Rolling.count` with ``min_periods=None`` to default to the size of the window (:issue:`31302`)
- Renamed ``fname`` to ``path`` in :meth:`DataFrame.to_parquet`, :meth:`DataFrame.to_stata` and :meth:`DataFrame.to_feather` (:issue:`30338`)
- Enforced disallowing indexing a :class:`Series` with a single item list with a slice (e.g. ``ser[[slice(0, 2)]]``). Either convert the list to tuple, or pass the slice directly instead (:issue:`31333`)
- Enforced disallowing indexing an :class:`Index` object with a float key which will raise an ``IndexError`` (:issue:`34191`).
- Enforced the ``display.max_colwidth`` option to not accept negative integers (:issue:`31569`)
- Removed the ``display.column_space`` option in favor of ``df.to_string(col_space=...)`` (:issue:`47280`)
- Removed the deprecated method ``mad`` from pandas classes (:issue:`11787`)
Expand Down
16 changes: 5 additions & 11 deletions pandas/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,30 +148,24 @@ def is_bool_indexer(key: Any) -> bool:
return False


def cast_scalar_indexer(val, warn_float: bool = False):
def cast_scalar_indexer(val):
"""
To avoid numpy DeprecationWarnings, cast float to integer where valid.

Parameters
----------
val : scalar
warn_float : bool, default False
If True, issue deprecation warning for a float indexer.

Returns
-------
outval : scalar
"""
# assumes lib.is_scalar(val)
if lib.is_float(val) and val.is_integer():
if warn_float:
warnings.warn(
"Indexing with a float is deprecated, and will raise an IndexError "
"in pandas 2.0. You can manually convert to an integer key instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return int(val)
raise IndexError(
"Indexing with a float is not allowed. Manually convert "
f"to {val} to an integer key instead.",
)
return val


Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5221,7 +5221,7 @@ def __getitem__(self, key):

if is_integer(key) or is_float(key):
# GH#44051 exclude bool, which would return a 2d ndarray
key = com.cast_scalar_indexer(key, warn_float=True)
key = com.cast_scalar_indexer(key)
return getitem(key)

if isinstance(key, slice):
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2031,7 +2031,7 @@ def __reduce__(self):

def __getitem__(self, key):
if is_scalar(key):
key = com.cast_scalar_indexer(key, warn_float=True)
key = com.cast_scalar_indexer(key)

retval = []
for lev, level_codes in zip(self.levels, self.codes):
Expand Down
11 changes: 4 additions & 7 deletions pandas/tests/indexes/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,11 @@ def test_putmask_with_wrong_mask(self, index):
@pytest.mark.parametrize(
"idx", [Index([1, 2, 3]), Index([0.1, 0.2, 0.3]), Index(["a", "b", "c"])]
)
def test_getitem_deprecated_float(idx):
# https://github.com/pandas-dev/pandas/issues/34191
def test_getitem_raises_float(idx):
# https://github.com/pandas-dev/pandas/issues/34191; enforced 2.0

with tm.assert_produces_warning(FutureWarning):
result = idx[1.0]

expected = idx[1]
assert result == expected
with pytest.raises(IndexError, match="Indexing with a float is not allowed"):
idx[1.0]


@pytest.mark.parametrize(
Expand Down