Skip to content

Commit 345ac8d

Browse files
authored
BUG: Series.loc[-1] with UInt64Index (#41777)
1 parent 346b2f2 commit 345ac8d

File tree

6 files changed

+26
-26
lines changed

6 files changed

+26
-26
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ Indexing
945945
- Bug in :meth:`DataFrame.loc` returning :class:`MultiIndex` in wrong order if indexer has duplicates (:issue:`40978`)
946946
- Bug in :meth:`DataFrame.__setitem__` raising ``TypeError`` when using a str subclass as the column name with a :class:`DatetimeIndex` (:issue:`37366`)
947947
- Bug in :meth:`PeriodIndex.get_loc` failing to raise ``KeyError`` when given a :class:`Period` with a mismatched ``freq`` (:issue:`41670`)
948+
- Bug ``.loc.__getitem__`` with a :class:`UInt64Index` and negative-integer keys raising ``OverflowError`` instead of ``KeyError`` in some cases, wrapping around to positive integers in others (:issue:`41777`)
948949

949950
Missing
950951
^^^^^^^

pandas/_libs/index.pyx

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ cdef class IndexEngine:
106106

107107
try:
108108
return self.mapping.get_item(val)
109-
except (TypeError, ValueError):
109+
except (TypeError, ValueError, OverflowError):
110+
# GH#41775 OverflowError e.g. if we are uint64 and val is -1
110111
raise KeyError(val)
111112

112113
cdef inline _get_loc_duplicates(self, object val):

pandas/core/indexes/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -5409,6 +5409,7 @@ def _find_common_type_compat(self, target) -> DtypeObj:
54095409
return np.dtype("object")
54105410

54115411
dtype = find_common_type([self.dtype, target_dtype])
5412+
54125413
if dtype.kind in ["i", "u"]:
54135414
# TODO: what about reversed with self being categorical?
54145415
if (

pandas/core/indexes/datetimelike.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
TimedeltaArray,
5050
)
5151
from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin
52-
import pandas.core.common as com
5352
import pandas.core.indexes.base as ibase
5453
from pandas.core.indexes.base import (
5554
Index,
@@ -599,7 +598,7 @@ def _convert_arr_indexer(self, keyarr):
599598
try:
600599
return self._data._validate_listlike(keyarr, allow_object=True)
601600
except (ValueError, TypeError):
602-
return com.asarray_tuplesafe(keyarr)
601+
return super()._convert_arr_indexer(keyarr)
603602

604603

605604
class DatetimeTimedeltaMixin(DatetimeIndexOpsMixin):

pandas/core/indexes/numeric.py

-16
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
)
3838
from pandas.core.dtypes.generic import ABCSeries
3939

40-
import pandas.core.common as com
4140
from pandas.core.indexes.base import (
4241
Index,
4342
maybe_extract_name,
@@ -250,21 +249,6 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
250249
# we will try to coerce to integers
251250
return self._maybe_cast_indexer(label)
252251

253-
@doc(Index._convert_arr_indexer)
254-
def _convert_arr_indexer(self, keyarr) -> np.ndarray:
255-
if not is_unsigned_integer_dtype(self.dtype):
256-
return super()._convert_arr_indexer(keyarr)
257-
258-
# Cast the indexer to uint64 if possible so that the values returned
259-
# from indexing are also uint64.
260-
dtype = None
261-
if is_integer_dtype(keyarr) or (
262-
lib.infer_dtype(keyarr, skipna=False) == "integer"
263-
):
264-
dtype = np.dtype(np.uint64)
265-
266-
return com.asarray_tuplesafe(keyarr, dtype=dtype)
267-
268252
# ----------------------------------------------------------------
269253

270254
@doc(Index._shallow_copy)

pandas/tests/indexing/test_loc.py

+21-7
Original file line numberDiff line numberDiff line change
@@ -1010,18 +1010,32 @@ def test_loc_copy_vs_view(self):
10101010
def test_loc_uint64(self):
10111011
# GH20722
10121012
# Test whether loc accept uint64 max value as index.
1013-
s = Series([1, 2], index=[np.iinfo("uint64").max - 1, np.iinfo("uint64").max])
1013+
umax = np.iinfo("uint64").max
1014+
ser = Series([1, 2], index=[umax - 1, umax])
10141015

1015-
result = s.loc[np.iinfo("uint64").max - 1]
1016-
expected = s.iloc[0]
1016+
result = ser.loc[umax - 1]
1017+
expected = ser.iloc[0]
10171018
assert result == expected
10181019

1019-
result = s.loc[[np.iinfo("uint64").max - 1]]
1020-
expected = s.iloc[[0]]
1020+
result = ser.loc[[umax - 1]]
1021+
expected = ser.iloc[[0]]
10211022
tm.assert_series_equal(result, expected)
10221023

1023-
result = s.loc[[np.iinfo("uint64").max - 1, np.iinfo("uint64").max]]
1024-
tm.assert_series_equal(result, s)
1024+
result = ser.loc[[umax - 1, umax]]
1025+
tm.assert_series_equal(result, ser)
1026+
1027+
def test_loc_uint64_disallow_negative(self):
1028+
# GH#41775
1029+
umax = np.iinfo("uint64").max
1030+
ser = Series([1, 2], index=[umax - 1, umax])
1031+
1032+
with pytest.raises(KeyError, match="-1"):
1033+
# don't wrap around
1034+
ser.loc[-1]
1035+
1036+
with pytest.raises(KeyError, match="-1"):
1037+
# don't wrap around
1038+
ser.loc[[-1]]
10251039

10261040
def test_loc_setitem_empty_append_expands_rows(self):
10271041
# GH6173, various appends to an empty dataframe

0 commit comments

Comments
 (0)