Skip to content

Commit 71bf9fa

Browse files
authored
REF: Share code between NumericIndex subclasses (#38027)
1 parent 43fa160 commit 71bf9fa

File tree

2 files changed

+27
-49
lines changed

2 files changed

+27
-49
lines changed

pandas/core/indexes/base.py

+11
Original file line numberDiff line numberDiff line change
@@ -5523,6 +5523,17 @@ def _cmp_method(self, other, op):
55235523
"""
55245524
Wrapper used to dispatch comparison operations.
55255525
"""
5526+
if self.is_(other):
5527+
# fastpath
5528+
if op in {operator.eq, operator.le, operator.ge}:
5529+
arr = np.ones(len(self), dtype=bool)
5530+
if self._can_hold_na and not isinstance(self, ABCMultiIndex):
5531+
# TODO: should set MultiIndex._can_hold_na = False?
5532+
arr[self.isna()] = False
5533+
return arr
5534+
elif op in {operator.ne, operator.lt, operator.gt}:
5535+
return np.zeros(len(self), dtype=bool)
5536+
55265537
if isinstance(other, (np.ndarray, Index, ABCSeries, ExtensionArray)):
55275538
if len(self) != len(other):
55285539
raise ValueError("Lengths must match to compare")

pandas/core/indexes/numeric.py

+16-49
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import operator
21
from typing import Any
32
import warnings
43

54
import numpy as np
65

76
from pandas._libs import index as libindex, lib
87
from pandas._typing import Dtype, Label
9-
from pandas.util._decorators import cache_readonly, doc
8+
from pandas.util._decorators import doc
109

1110
from pandas.core.dtypes.cast import astype_nansafe
1211
from pandas.core.dtypes.common import (
@@ -188,18 +187,6 @@ def _union(self, other, sort):
188187
else:
189188
return super()._union(other, sort)
190189

191-
def _cmp_method(self, other, op):
192-
if self.is_(other): # fastpath
193-
if op in {operator.eq, operator.le, operator.ge}:
194-
arr = np.ones(len(self), dtype=bool)
195-
if self._can_hold_na:
196-
arr[self.isna()] = False
197-
return arr
198-
elif op in {operator.ne, operator.lt, operator.gt}:
199-
return np.zeros(len(self), dtype=bool)
200-
201-
return super()._cmp_method(other, op)
202-
203190

204191
_num_index_shared_docs[
205192
"class_descr"
@@ -243,6 +230,20 @@ class IntegerIndex(NumericIndex):
243230
"""
244231

245232
_default_dtype: np.dtype
233+
_can_hold_na = False
234+
235+
@classmethod
236+
def _assert_safe_casting(cls, data, subarr):
237+
"""
238+
Ensure incoming data can be represented with matching signed-ness.
239+
"""
240+
if data.dtype.kind != cls._default_dtype.kind:
241+
if not np.array_equal(data, subarr):
242+
raise TypeError("Unsafe NumPy casting, you must explicitly cast")
243+
244+
def _can_union_without_object_cast(self, other) -> bool:
245+
# See GH#26778, further casting may occur in NumericIndex._union
246+
return other.dtype == "f8" or other.dtype == self.dtype
246247

247248
def __contains__(self, key) -> bool:
248249
"""
@@ -278,23 +279,9 @@ class Int64Index(IntegerIndex):
278279
__doc__ = _num_index_shared_docs["class_descr"] % _int64_descr_args
279280

280281
_typ = "int64index"
281-
_can_hold_na = False
282282
_engine_type = libindex.Int64Engine
283283
_default_dtype = np.dtype(np.int64)
284284

285-
@classmethod
286-
def _assert_safe_casting(cls, data, subarr):
287-
"""
288-
Ensure incoming data can be represented as ints.
289-
"""
290-
if not issubclass(data.dtype.type, np.signedinteger):
291-
if not np.array_equal(data, subarr):
292-
raise TypeError("Unsafe NumPy casting, you must explicitly cast")
293-
294-
def _can_union_without_object_cast(self, other) -> bool:
295-
# See GH#26778, further casting may occur in NumericIndex._union
296-
return other.dtype == "f8" or other.dtype == self.dtype
297-
298285

299286
_uint64_descr_args = dict(
300287
klass="UInt64Index", ltype="unsigned integer", dtype="uint64", extra=""
@@ -305,7 +292,6 @@ class UInt64Index(IntegerIndex):
305292
__doc__ = _num_index_shared_docs["class_descr"] % _uint64_descr_args
306293

307294
_typ = "uint64index"
308-
_can_hold_na = False
309295
_engine_type = libindex.UInt64Engine
310296
_default_dtype = np.dtype(np.uint64)
311297

@@ -324,21 +310,6 @@ def _convert_arr_indexer(self, keyarr):
324310

325311
return com.asarray_tuplesafe(keyarr, dtype=dtype)
326312

327-
# ----------------------------------------------------------------
328-
329-
@classmethod
330-
def _assert_safe_casting(cls, data, subarr):
331-
"""
332-
Ensure incoming data can be represented as uints.
333-
"""
334-
if not issubclass(data.dtype.type, np.unsignedinteger):
335-
if not np.array_equal(data, subarr):
336-
raise TypeError("Unsafe NumPy casting, you must explicitly cast")
337-
338-
def _can_union_without_object_cast(self, other) -> bool:
339-
# See GH#26778, further casting may occur in NumericIndex._union
340-
return other.dtype == "f8" or other.dtype == self.dtype
341-
342313

343314
_float64_descr_args = dict(
344315
klass="Float64Index", dtype="float64", ltype="float", extra=""
@@ -350,7 +321,7 @@ class Float64Index(NumericIndex):
350321

351322
_typ = "float64index"
352323
_engine_type = libindex.Float64Engine
353-
_default_dtype = np.float64
324+
_default_dtype = np.dtype(np.float64)
354325

355326
@property
356327
def inferred_type(self) -> str:
@@ -429,10 +400,6 @@ def __contains__(self, other: Any) -> bool:
429400

430401
return is_float(other) and np.isnan(other) and self.hasnans
431402

432-
@cache_readonly
433-
def is_unique(self) -> bool:
434-
return super().is_unique and self._nan_idxs.size < 2
435-
436403
def _can_union_without_object_cast(self, other) -> bool:
437404
# See GH#26778, further casting may occur in NumericIndex._union
438405
return is_numeric_dtype(other.dtype)

0 commit comments

Comments
 (0)