From f2708aa8dc72ba88e52c14a1707c601a449ad269 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Thu, 2 Feb 2023 21:14:47 +0000 Subject: [PATCH 1/3] DEPR: Remove NumericIndex from tests/indexes/test_numpy_compat.py --- pandas/tests/indexes/test_numpy_compat.py | 25 +++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/pandas/tests/indexes/test_numpy_compat.py b/pandas/tests/indexes/test_numpy_compat.py index cdc5446bfeba3..2a29e57678df9 100644 --- a/pandas/tests/indexes/test_numpy_compat.py +++ b/pandas/tests/indexes/test_numpy_compat.py @@ -10,8 +10,10 @@ isna, ) import pandas._testing as tm -from pandas.api.types import is_complex_dtype -from pandas.core.api import NumericIndex +from pandas.api.types import ( + is_complex_dtype, + is_numeric_dtype, +) from pandas.core.arrays import BooleanArray from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin @@ -66,11 +68,8 @@ def test_numpy_ufuncs_basic(index, func): with tm.external_error_raised((TypeError, AttributeError)): with np.errstate(all="ignore"): func(index) - elif ( - isinstance(index, NumericIndex) - or (not isinstance(index.dtype, np.dtype) and index.dtype._is_numeric) - or (index.dtype.kind == "c" and func not in [np.deg2rad, np.rad2deg]) - or index.dtype == bool + elif is_numeric_dtype(index) and not ( + is_complex_dtype(index) and func in [np.deg2rad, np.rad2deg] ): # coerces to float (e.g. np.sin) with np.errstate(all="ignore"): @@ -81,10 +80,9 @@ def test_numpy_ufuncs_basic(index, func): exp = Index(arr_result, name=index.name) tm.assert_index_equal(result, exp) - if type(index) is not Index or index.dtype == bool: - assert type(result) is NumericIndex + if isinstance(index.dtype, np.dtype) and is_numeric_dtype(index): if is_complex_dtype(index): - assert result.dtype == "complex64" + assert result.dtype == index.dtype elif index.dtype in ["bool", "int8", "uint8"]: assert result.dtype in ["float16", "float32"] elif index.dtype in ["int16", "uint16", "float32"]: @@ -128,11 +126,8 @@ def test_numpy_ufuncs_other(index, func): with tm.external_error_raised(TypeError): func(index) - elif ( - isinstance(index, NumericIndex) - or (not isinstance(index.dtype, np.dtype) and index.dtype._is_numeric) - or (index.dtype.kind == "c" and func is not np.signbit) - or index.dtype == bool + elif is_numeric_dtype(index) and not ( + is_complex_dtype(index) and func is np.signbit ): # Results in bool array result = func(index) From b6a1567fec760baba61d611d0ccb33138f10c072 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Fri, 3 Feb 2023 07:28:57 +0000 Subject: [PATCH 2/3] DEPR: Remove NumericIndex from code base --- pandas/_testing/asserters.py | 6 +----- pandas/core/algorithms.py | 5 ++--- pandas/core/api.py | 2 -- pandas/core/base.py | 2 +- pandas/core/dtypes/generic.py | 1 - pandas/core/indexes/api.py | 2 -- pandas/core/indexes/base.py | 16 ++-------------- pandas/core/indexes/numeric.py | 7 ------- pandas/core/indexes/range.py | 7 +++---- pandas/io/formats/info.py | 4 ++-- pandas/tests/frame/indexing/test_indexing.py | 2 +- pandas/tests/indexes/multi/test_names.py | 1 - pandas/tests/indexes/numeric/test_numeric.py | 2 -- pandas/tests/indexes/test_any_index.py | 2 -- pandas/tests/indexes/test_common.py | 3 +-- pandas/tests/resample/test_resample_api.py | 2 +- 16 files changed, 14 insertions(+), 50 deletions(-) delete mode 100644 pandas/core/indexes/numeric.py diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 3e171b57af3ba..87262bc57c919 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -363,11 +363,7 @@ def is_class_equiv(idx: Index) -> bool: This only checks class equivalence. There is a separate check that the dtype is int64. """ - from pandas.core.indexes.numeric import NumericIndex - - if isinstance(idx, RangeIndex): - return True - elif type(idx) is Index or type(idx) is NumericIndex: + if type(idx) is Index or isinstance(idx, RangeIndex): return True else: return False diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 1a22c3fe327e9..0037cd20e8c1e 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -1313,8 +1313,7 @@ def __init__(self, obj: DataFrame, n: int, keep: str, columns: IndexLabel) -> No self.columns = columns def compute(self, method: str) -> DataFrame: - - from pandas.core.api import NumericIndex + from pandas.core.api import Index n = self.n frame = self.obj @@ -1342,7 +1341,7 @@ def get_indexer(current_indexer, other_indexer): original_index = frame.index cur_frame = frame = frame.reset_index(drop=True) cur_n = n - indexer = NumericIndex([], dtype=np.int64) + indexer = Index([], dtype=np.int64) for i, column in enumerate(columns): # For each column we apply method to cur_frame[column]. diff --git a/pandas/core/api.py b/pandas/core/api.py index 0dffa681acfc1..c0b828d9330b4 100644 --- a/pandas/core/api.py +++ b/pandas/core/api.py @@ -54,7 +54,6 @@ Index, IntervalIndex, MultiIndex, - NumericIndex, PeriodIndex, RangeIndex, TimedeltaIndex, @@ -117,7 +116,6 @@ "NaT", "notna", "notnull", - "NumericIndex", "Period", "PeriodDtype", "PeriodIndex", diff --git a/pandas/core/base.py b/pandas/core/base.py index ab7a79162a0f2..b708ff44b39d0 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -1161,7 +1161,7 @@ def factorize( uniques = uniques.astype(np.float32) if isinstance(self, ABCIndex): - # preserve e.g. NumericIndex, preserve MultiIndex + # preserve e.g. MultiIndex uniques = self._constructor(uniques) else: from pandas import Index diff --git a/pandas/core/dtypes/generic.py b/pandas/core/dtypes/generic.py index 190bd9d940ca3..5904ba4895aef 100644 --- a/pandas/core/dtypes/generic.py +++ b/pandas/core/dtypes/generic.py @@ -93,7 +93,6 @@ def _subclasscheck(cls, inst) -> bool: { "index", "rangeindex", - "numericindex", "multiindex", "datetimeindex", "timedeltaindex", diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 08191363bfc93..fcf529f5be9ac 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -26,7 +26,6 @@ from pandas.core.indexes.datetimes import DatetimeIndex from pandas.core.indexes.interval import IntervalIndex from pandas.core.indexes.multi import MultiIndex -from pandas.core.indexes.numeric import NumericIndex from pandas.core.indexes.period import PeriodIndex from pandas.core.indexes.range import RangeIndex from pandas.core.indexes.timedeltas import TimedeltaIndex @@ -46,7 +45,6 @@ __all__ = [ "Index", "MultiIndex", - "NumericIndex", "CategoricalIndex", "IntervalIndex", "RangeIndex", diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index e1092996abce5..b607d170d5385 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -317,7 +317,6 @@ class Index(IndexOpsMixin, PandasObject): DatetimeIndex : Index of datetime64 data. TimedeltaIndex : Index of timedelta64 data. PeriodIndex : Index of Period data. - NumericIndex : Index of numpy int/uint/float data. Notes ----- @@ -539,7 +538,6 @@ def __new__( klass = cls._dtype_to_subclass(arr.dtype) - # _ensure_array _may_ be unnecessary once NumericIndex etc are gone arr = klass._ensure_array(arr, arr.dtype, copy=False) return klass._simple_new(arr, name) @@ -596,18 +594,11 @@ def _dtype_to_subclass(cls, dtype: DtypeObj): return TimedeltaIndex - elif dtype.kind in ["i", "f", "u"]: - from pandas.core.api import NumericIndex - - return NumericIndex - elif dtype.kind == "O": # NB: assuming away MultiIndex return Index - elif issubclass( - dtype.type, (str, bool, np.bool_, complex, np.complex64, np.complex128) - ): + elif issubclass(dtype.type, str) or is_numeric_dtype(dtype): return Index raise NotImplementedError(dtype) @@ -1207,10 +1198,6 @@ def __repr__(self) -> str_t: Return a string representation for this object. """ klass_name = type(self).__name__ - from pandas.core.indexes.numeric import NumericIndex - - if type(self) is NumericIndex: - klass_name = "Index" data = self._format_data() attrs = self._format_attrs() space = self._format_space() @@ -5375,6 +5362,7 @@ def identical(self, other) -> bool: for c in self._comparables ) and type(self) == type(other) + and self.dtype == other.dtype ) @final diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py deleted file mode 100644 index 8113b5ea2bb2a..0000000000000 --- a/pandas/core/indexes/numeric.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import annotations - -from pandas.core.indexes.base import Index - - -class NumericIndex(Index): - pass diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 144665401a2a0..ca34fcfc7a625 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -49,13 +49,12 @@ Index, maybe_extract_name, ) -from pandas.core.indexes.numeric import NumericIndex from pandas.core.ops.common import unpack_zerodim_and_defer _empty_range = range(0) -class RangeIndex(NumericIndex): +class RangeIndex(Index): """ Immutable Index implementing a monotonic integer range. @@ -196,7 +195,7 @@ def _validate_dtype(cls, dtype: Dtype | None) -> None: @cache_readonly def _constructor(self) -> type[Index]: # type: ignore[override] """return the class to use for construction""" - return NumericIndex + return Index # error: Signature of "_data" incompatible with supertype "Index" @cache_readonly @@ -408,7 +407,7 @@ def _shallow_copy(self, values, name: Hashable = no_default): new_range = range(values[0], values[-1] + diff, diff) return type(self)._simple_new(new_range, name=name) else: - return NumericIndex._simple_new(values, name=name) + return self._constructor._simple_new(values, name=name) def _view(self: RangeIndex) -> RangeIndex: result = type(self)._simple_new(self._range, name=self._name) diff --git a/pandas/io/formats/info.py b/pandas/io/formats/info.py index 9a93724ca8f37..d826c0a148ebe 100644 --- a/pandas/io/formats/info.py +++ b/pandas/io/formats/info.py @@ -165,7 +165,7 @@ >>> s = pd.Series(text_values, index=int_values) >>> s.info() - NumericIndex: 5 entries, 1 to 5 + Index: 5 entries, 1 to 5 Series name: None Non-Null Count Dtype -------------- ----- @@ -177,7 +177,7 @@ >>> s.info(verbose=False) - NumericIndex: 5 entries, 1 to 5 + Index: 5 entries, 1 to 5 dtypes: object(1) memory usage: 80.0+ bytes diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index 8bb5948029ca1..4bb7f62fb13bd 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -737,7 +737,7 @@ def test_getitem_setitem_float_labels(self, using_array_manager): # positional slicing only via iloc! msg = ( - "cannot do positional indexing on NumericIndex with " + "cannot do positional indexing on Index with " r"these indexers \[1.0\] of type float" ) with pytest.raises(TypeError, match=msg): diff --git a/pandas/tests/indexes/multi/test_names.py b/pandas/tests/indexes/multi/test_names.py index 5e3a427bc75ba..e9c65d32cbcd7 100644 --- a/pandas/tests/indexes/multi/test_names.py +++ b/pandas/tests/indexes/multi/test_names.py @@ -146,7 +146,6 @@ def test_setting_names_from_levels_raises(): new.index.name = "bar" assert pd.Index._no_setting_name is False - assert pd.core.api.NumericIndex._no_setting_name is False assert pd.RangeIndex._no_setting_name is False diff --git a/pandas/tests/indexes/numeric/test_numeric.py b/pandas/tests/indexes/numeric/test_numeric.py index 68da64805ad1e..ed8071afe2ee2 100644 --- a/pandas/tests/indexes/numeric/test_numeric.py +++ b/pandas/tests/indexes/numeric/test_numeric.py @@ -43,8 +43,6 @@ def float_index(self, dtype): return self._index_cls([0.0, 2.5, 5.0, 7.5, 10.0], dtype=dtype) def test_repr_roundtrip(self, index): - from pandas.core.api import NumericIndex # noqa: F401 - tm.assert_index_equal(eval(repr(index)), index, exact=True) def check_coerce(self, a, b, is_float_index=True): diff --git a/pandas/tests/indexes/test_any_index.py b/pandas/tests/indexes/test_any_index.py index fdea2945a8c0b..3b3d6dbaf697f 100644 --- a/pandas/tests/indexes/test_any_index.py +++ b/pandas/tests/indexes/test_any_index.py @@ -154,8 +154,6 @@ def test_str(self, index): # test the string repr index.name = "foo" assert "'foo'" in str(index) - if type(index).__name__ == "NumericIndex": # TODO: remove NumericIndex - return assert type(index).__name__ in str(index) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 957e7031f9bf6..40440bd8e0ff8 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -31,7 +31,6 @@ RangeIndex, ) import pandas._testing as tm -from pandas.core.api import NumericIndex class TestCommon: @@ -431,7 +430,7 @@ def test_hasnans_isnans(self, index_flat): if len(index) == 0: return - elif isinstance(index, NumericIndex) and is_integer_dtype(index.dtype): + elif is_integer_dtype(index.dtype): return elif index.dtype == bool: # values[1] = np.nan below casts to True! diff --git a/pandas/tests/resample/test_resample_api.py b/pandas/tests/resample/test_resample_api.py index 51a65d88d7b32..77b068aba765c 100644 --- a/pandas/tests/resample/test_resample_api.py +++ b/pandas/tests/resample/test_resample_api.py @@ -646,7 +646,7 @@ def test_selection_api_validation(): # non DatetimeIndex msg = ( "Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, " - "but got an instance of 'NumericIndex'" + "but got an instance of 'Index'" ) with pytest.raises(TypeError, match=msg): df.resample("2D", level="v") From a97219656b4f0c05132bdbafcaa6b4d339d53a49 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Fri, 3 Feb 2023 08:47:52 +0000 Subject: [PATCH 3/3] obey pylint (simplifiable if statement) --- pandas/_testing/asserters.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 87262bc57c919..818ea1e6ef9d0 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -363,10 +363,7 @@ def is_class_equiv(idx: Index) -> bool: This only checks class equivalence. There is a separate check that the dtype is int64. """ - if type(idx) is Index or isinstance(idx, RangeIndex): - return True - else: - return False + return type(idx) is Index or isinstance(idx, RangeIndex) if type(left) == type(right): return