Skip to content

Commit cb35d8a

Browse files
DEPR: deprecate Index.__getitem__ with float key (#34193)
1 parent 5d8bb30 commit cb35d8a

File tree

6 files changed

+33
-3
lines changed

6 files changed

+33
-3
lines changed

doc/source/whatsnew/v1.1.0.rst

+3
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ Deprecations
590590
- :func:`pandas.api.types.is_categorical` is deprecated and will be removed in a future version; use `:func:pandas.api.types.is_categorical_dtype` instead (:issue:`33385`)
591591
- :meth:`Index.get_value` is deprecated and will be removed in a future version (:issue:`19728`)
592592
- :meth:`DateOffset.__call__` is deprecated and will be removed in a future version, use ``offset + other`` instead (:issue:`34171`)
593+
- Indexing an :class:`Index` object with a float key is deprecated, and will
594+
raise an ``IndexError`` in the future. You can manually convert to an integer key
595+
instead (:issue:`34191`).
593596
- The ``squeeze`` keyword in the ``groupby`` function is deprecated and will be removed in a future version (:issue:`32380`)
594597

595598
.. ---------------------------------------------------------------------------

pandas/core/common.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from functools import partial
1010
import inspect
1111
from typing import Any, Collection, Iterable, List, Union
12+
import warnings
1213

1314
import numpy as np
1415

@@ -144,20 +145,29 @@ def is_bool_indexer(key: Any) -> bool:
144145
return False
145146

146147

147-
def cast_scalar_indexer(val):
148+
def cast_scalar_indexer(val, warn_float=False):
148149
"""
149150
To avoid numpy DeprecationWarnings, cast float to integer where valid.
150151
151152
Parameters
152153
----------
153154
val : scalar
155+
warn_float : bool, default False
156+
If True, issue deprecation warning for a float indexer.
154157
155158
Returns
156159
-------
157160
outval : scalar
158161
"""
159162
# assumes lib.is_scalar(val)
160163
if lib.is_float(val) and val.is_integer():
164+
if warn_float:
165+
warnings.warn(
166+
"Indexing with a float is deprecated, and will raise an IndexError "
167+
"in pandas 2.0. You can manually convert to an integer key instead.",
168+
FutureWarning,
169+
stacklevel=3,
170+
)
161171
return int(val)
162172
return val
163173

pandas/core/indexes/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4041,7 +4041,7 @@ def __getitem__(self, key):
40414041
promote = self._shallow_copy
40424042

40434043
if is_scalar(key):
4044-
key = com.cast_scalar_indexer(key)
4044+
key = com.cast_scalar_indexer(key, warn_float=True)
40454045
return getitem(key)
40464046

40474047
if isinstance(key, slice):

pandas/core/indexes/multi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1896,7 +1896,7 @@ def __reduce__(self):
18961896

18971897
def __getitem__(self, key):
18981898
if is_scalar(key):
1899-
key = com.cast_scalar_indexer(key)
1899+
key = com.cast_scalar_indexer(key, warn_float=True)
19001900

19011901
retval = []
19021902
for lev, level_codes in zip(self.levels, self.codes):

pandas/plotting/_matplotlib/core.py

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from pandas.util._decorators import cache_readonly
99

1010
from pandas.core.dtypes.common import (
11+
is_float,
1112
is_hashable,
1213
is_integer,
1314
is_iterator,
@@ -1188,6 +1189,8 @@ def _post_plot_logic(self, ax, data):
11881189
from matplotlib.ticker import FixedLocator
11891190

11901191
def get_label(i):
1192+
if is_float(i) and i.is_integer():
1193+
i = int(i)
11911194
try:
11921195
return pprint_thing(data.index[i])
11931196
except Exception:

pandas/tests/indexes/test_indexing.py

+14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import pytest
1818

1919
from pandas import Float64Index, Index, Int64Index, UInt64Index
20+
import pandas._testing as tm
2021

2122

2223
class TestContains:
@@ -82,3 +83,16 @@ def test_contains_with_float_index(self):
8283
assert 1.1 in float_index
8384
assert 1.0 not in float_index
8485
assert 1 not in float_index
86+
87+
88+
@pytest.mark.parametrize(
89+
"idx", [Index([1, 2, 3]), Index([0.1, 0.2, 0.3]), Index(["a", "b", "c"])]
90+
)
91+
def test_getitem_deprecated_float(idx):
92+
# https://github.com/pandas-dev/pandas/issues/34191
93+
94+
with tm.assert_produces_warning(FutureWarning):
95+
result = idx[1.0]
96+
97+
expected = idx[1]
98+
assert result == expected

0 commit comments

Comments
 (0)