Skip to content

Commit 1c113db

Browse files
yeojin-devjreback
authored andcommitted
BUG: Check types in Index.__contains__ (#22085) (#22602)
1 parent f87fe14 commit 1c113db

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

doc/source/whatsnew/v0.24.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ Indexing
723723
- ``Float64Index.get_loc`` now raises ``KeyError`` when boolean key passed. (:issue:`19087`)
724724
- Bug in :meth:`DataFrame.loc` when indexing with an :class:`IntervalIndex` (:issue:`19977`)
725725
- :class:`Index` no longer mangles ``None``, ``NaN`` and ``NaT``, i.e. they are treated as three different keys. However, for numeric Index all three are still coerced to a ``NaN`` (:issue:`22332`)
726+
- Bug in `scalar in Index` if scalar is a float while the ``Index`` is of integer dtype (:issue:`22085`)
726727

727728
Missing
728729
^^^^^^^

pandas/core/indexes/numeric.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
pandas_dtype,
77
needs_i8_conversion,
88
is_integer_dtype,
9+
is_float,
910
is_bool,
1011
is_bool_dtype,
1112
is_scalar)
@@ -162,7 +163,25 @@ def insert(self, loc, item):
162163
)
163164

164165

165-
class Int64Index(NumericIndex):
166+
class IntegerIndex(NumericIndex):
167+
"""
168+
This is an abstract class for Int64Index, UInt64Index.
169+
"""
170+
171+
def __contains__(self, key):
172+
"""
173+
Check if key is a float and has a decimal. If it has, return False.
174+
"""
175+
hash(key)
176+
try:
177+
if is_float(key) and int(key) != key:
178+
return False
179+
return key in self._engine
180+
except (OverflowError, TypeError, ValueError):
181+
return False
182+
183+
184+
class Int64Index(IntegerIndex):
166185
__doc__ = _num_index_shared_docs['class_descr'] % _int64_descr_args
167186

168187
_typ = 'int64index'
@@ -220,7 +239,7 @@ def _assert_safe_casting(cls, data, subarr):
220239
)
221240

222241

223-
class UInt64Index(NumericIndex):
242+
class UInt64Index(IntegerIndex):
224243
__doc__ = _num_index_shared_docs['class_descr'] % _uint64_descr_args
225244

226245
_typ = 'uint64index'

pandas/tests/indexing/test_indexing.py

+15
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,21 @@ def test_mixed_index_not_contains(self, index, val):
631631
# GH 19860
632632
assert val not in index
633633

634+
def test_contains_with_float_index(self):
635+
# GH#22085
636+
integer_index = pd.Int64Index([0, 1, 2, 3])
637+
uinteger_index = pd.UInt64Index([0, 1, 2, 3])
638+
float_index = pd.Float64Index([0.1, 1.1, 2.2, 3.3])
639+
640+
for index in (integer_index, uinteger_index):
641+
assert 1.1 not in index
642+
assert 1.0 in index
643+
assert 1 in index
644+
645+
assert 1.1 in float_index
646+
assert 1.0 not in float_index
647+
assert 1 not in float_index
648+
634649
def test_index_type_coercion(self):
635650

636651
with catch_warnings(record=True):

0 commit comments

Comments
 (0)