Skip to content

Commit 7fc2273

Browse files
Terji PetersenTerji Petersen
authored andcommitted
DEPR: move NumericIndexes into base Index, part 1
1 parent d49eee3 commit 7fc2273

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+296
-363
lines changed

pandas/__init__.py

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -183,38 +183,6 @@
183183
__git_version__ = v.get("full-revisionid")
184184
del get_versions, v
185185

186-
# GH 27101
187-
__deprecated_num_index_names = ["Float64Index", "Int64Index", "UInt64Index"]
188-
189-
190-
def __dir__() -> list[str]:
191-
# GH43028
192-
# Int64Index etc. are deprecated, but we still want them to be available in the dir.
193-
# Remove in Pandas 2.0, when we remove Int64Index etc. from the code base.
194-
return list(globals().keys()) + __deprecated_num_index_names
195-
196-
197-
def __getattr__(name):
198-
import warnings
199-
200-
if name in __deprecated_num_index_names:
201-
warnings.warn(
202-
f"pandas.{name} is deprecated "
203-
"and will be removed from pandas in a future version. "
204-
"Use pandas.Index with the appropriate dtype instead.",
205-
FutureWarning,
206-
stacklevel=2,
207-
)
208-
from pandas.core.api import Float64Index, Int64Index, UInt64Index
209-
210-
return {
211-
"Float64Index": Float64Index,
212-
"Int64Index": Int64Index,
213-
"UInt64Index": UInt64Index,
214-
}[name]
215-
216-
raise AttributeError(f"module 'pandas' has no attribute '{name}'")
217-
218186

219187
# module level doc-string
220188
__doc__ = """

pandas/core/frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11203,7 +11203,7 @@ def quantile(
1120311203
)
1120411204
if method == "single":
1120511205
# error: Argument "qs" to "quantile" of "BlockManager" has incompatible type
11206-
# "Index"; expected "Float64Index"
11206+
# "Index"; expected "NumericIndex"
1120711207
res = data._mgr.quantile(
1120811208
qs=q, axis=1, interpolation=interpolation # type: ignore[arg-type]
1120911209
)

pandas/core/indexes/base.py

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
ensure_platform_int,
9292
is_bool_dtype,
9393
is_categorical_dtype,
94+
is_complex_dtype,
9495
is_dtype_equal,
9596
is_ea_or_datetimelike_dtype,
9697
is_extension_array_dtype,
@@ -590,18 +591,14 @@ def _dtype_to_subclass(cls, dtype: DtypeObj):
590591

591592
return TimedeltaIndex
592593

593-
elif dtype.kind == "f":
594-
from pandas.core.api import Float64Index
595-
596-
return Float64Index
597-
elif dtype.kind == "u":
598-
from pandas.core.api import UInt64Index
599-
600-
return UInt64Index
601-
elif dtype.kind == "i":
602-
from pandas.core.api import Int64Index
594+
elif (
595+
is_numeric_dtype(dtype)
596+
and not is_bool_dtype(dtype)
597+
and not is_complex_dtype(dtype)
598+
):
599+
from pandas.core.api import NumericIndex
603600

604-
return Int64Index
601+
return NumericIndex
605602

606603
elif dtype.kind == "O":
607604
# NB: assuming away MultiIndex
@@ -1057,14 +1054,29 @@ def astype(self, dtype, copy: bool = True):
10571054
) from err
10581055

10591056
# pass copy=False because any copying will be done in the astype above
1060-
if self._is_backward_compat_public_numeric_index:
1061-
# this block is needed so e.g. NumericIndex[int8].astype("int32") returns
1062-
# NumericIndex[int32] and not Int64Index with dtype int64.
1057+
if not self._is_backward_compat_public_numeric_index and not isinstance(
1058+
self, ABCRangeIndex
1059+
):
1060+
# this block is needed so e.g. Int64Index.astype("int32") returns
1061+
# Int64Index and not a NumericIndex with dtype int32.
10631062
# When Int64Index etc. are removed from the code base, removed this also.
10641063
if isinstance(dtype, np.dtype) and is_numeric_dtype(dtype):
1065-
return self._constructor(
1066-
new_values, name=self.name, dtype=dtype, copy=False
1064+
from pandas.core.api import (
1065+
Float64Index,
1066+
Int64Index,
1067+
UInt64Index,
10671068
)
1069+
1070+
if is_signed_integer_dtype(dtype):
1071+
klass = Int64Index
1072+
elif is_unsigned_integer_dtype(dtype):
1073+
klass = UInt64Index
1074+
elif is_float_dtype(dtype):
1075+
klass = Float64Index
1076+
else:
1077+
klass = Index
1078+
return klass(new_values, name=self.name, dtype=dtype, copy=False)
1079+
10681080
return Index(new_values, name=self.name, dtype=new_values.dtype, copy=False)
10691081

10701082
_index_shared_docs[
@@ -5265,6 +5277,7 @@ def putmask(self, mask, value) -> Index:
52655277
if self.dtype != object and is_valid_na_for_dtype(value, self.dtype):
52665278
# e.g. None -> np.nan, see also Block._standardize_fill_value
52675279
value = self._na_value
5280+
52685281
try:
52695282
converted = self._validate_fill_value(value)
52705283
except (LossySetitemError, ValueError, TypeError) as err:
@@ -6133,13 +6146,6 @@ def map(self, mapper, na_action=None):
61336146
new_values, self.dtype, same_dtype=same_dtype
61346147
)
61356148

6136-
if self._is_backward_compat_public_numeric_index and is_numeric_dtype(
6137-
new_values.dtype
6138-
):
6139-
return self._constructor(
6140-
new_values, dtype=dtype, copy=False, name=self.name
6141-
)
6142-
61436149
return Index._with_infer(new_values, dtype=dtype, copy=False, name=self.name)
61446150

61456151
# TODO: De-duplicate with map, xref GH#32349
@@ -6616,10 +6622,17 @@ def insert(self, loc: int, item) -> Index:
66166622
loc = loc if loc >= 0 else loc - 1
66176623
new_values[loc] = item
66186624

6619-
if self._typ == "numericindex":
6620-
# Use self._constructor instead of Index to retain NumericIndex GH#43921
6621-
# TODO(2.0) can use Index instead of self._constructor
6622-
return self._constructor._with_infer(new_values, name=self.name)
6625+
if not self._is_backward_compat_public_numeric_index:
6626+
from pandas.core.indexes.numeric import NumericIndex
6627+
6628+
if not isinstance(self, ABCRangeIndex) or not isinstance(
6629+
self, NumericIndex
6630+
):
6631+
return Index._with_infer(new_values, name=self.name)
6632+
else:
6633+
# Use self._constructor instead of Index to retain old-style num. index
6634+
# TODO(2.0) can use Index instead of self._constructor
6635+
return self._constructor._with_infer(new_values, name=self.name)
66236636
else:
66246637
return Index._with_infer(new_values, name=self.name)
66256638

pandas/core/indexes/numeric.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
)
1414
from pandas._typing import (
1515
Dtype,
16+
DtypeObj,
1617
npt,
1718
)
1819
from pandas.util._decorators import (
@@ -347,7 +348,26 @@ def _format_native_types(
347348
"""
348349

349350

350-
class IntegerIndex(NumericIndex):
351+
class TempBaseIndex(NumericIndex):
352+
@classmethod
353+
def _dtype_to_subclass(cls, dtype: DtypeObj):
354+
if is_integer_dtype(dtype):
355+
from pandas.core.api import Int64Index
356+
357+
return Int64Index
358+
elif is_unsigned_integer_dtype(dtype):
359+
from pandas.core.api import UInt64Index
360+
361+
return UInt64Index
362+
elif is_float_dtype(dtype):
363+
from pandas.core.api import Float64Index
364+
365+
return Float64Index
366+
else:
367+
return super()._dtype_to_subclass(dtype)
368+
369+
370+
class IntegerIndex(TempBaseIndex):
351371
"""
352372
This is an abstract class for Int64Index, UInt64Index.
353373
"""
@@ -391,7 +411,7 @@ def _engine_type(self) -> type[libindex.UInt64Engine]:
391411
return libindex.UInt64Engine
392412

393413

394-
class Float64Index(NumericIndex):
414+
class Float64Index(TempBaseIndex):
395415
_index_descr_args = {
396416
"klass": "Float64Index",
397417
"dtype": "float64",

pandas/core/indexes/range.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ def _simple_new(cls, values: range, name: Hashable = None) -> RangeIndex:
185185
# error: Return type "Type[Int64Index]" of "_constructor" incompatible with return
186186
# type "Type[RangeIndex]" in supertype "Index"
187187
@cache_readonly
188-
def _constructor(self) -> type[Int64Index]: # type: ignore[override]
188+
def _constructor(self) -> type[NumericIndex]: # type: ignore[override]
189189
"""return the class to use for construction"""
190-
return Int64Index
190+
return NumericIndex
191191

192192
# error: Signature of "_data" incompatible with supertype "Index"
193193
@cache_readonly

pandas/core/internals/managers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@
6464
)
6565
from pandas.core.indexers import maybe_convert_indices
6666
from pandas.core.indexes.api import (
67-
Float64Index,
6867
Index,
68+
NumericIndex,
6969
ensure_index,
7070
)
7171
from pandas.core.internals.base import (
@@ -1582,7 +1582,7 @@ def _equal_values(self: BlockManager, other: BlockManager) -> bool:
15821582
def quantile(
15831583
self: T,
15841584
*,
1585-
qs: Float64Index,
1585+
qs: NumericIndex,
15861586
axis: AxisInt = 0,
15871587
interpolation: QuantileInterpolation = "linear",
15881588
) -> T:
@@ -1610,7 +1610,7 @@ def quantile(
16101610
assert axis == 1 # only ever called this way
16111611

16121612
new_axes = list(self.axes)
1613-
new_axes[1] = Float64Index(qs)
1613+
new_axes[1] = Index(qs, dtype=np.float64)
16141614

16151615
blocks = [
16161616
blk.quantile(axis=axis, qs=qs, interpolation=interpolation)

pandas/tests/api/test_api.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,14 @@ class TestPDApi(Base):
5555
"DatetimeIndex",
5656
"ExcelFile",
5757
"ExcelWriter",
58-
"Float64Index",
5958
"Flags",
6059
"Grouper",
6160
"HDFStore",
6261
"Index",
63-
"Int64Index",
6462
"MultiIndex",
6563
"Period",
6664
"PeriodIndex",
6765
"RangeIndex",
68-
"UInt64Index",
6966
"Series",
7067
"SparseDtype",
7168
"StringDtype",
@@ -93,7 +90,7 @@ class TestPDApi(Base):
9390
]
9491

9592
# these are already deprecated; awaiting removal
96-
deprecated_classes: list[str] = ["Float64Index", "Int64Index", "UInt64Index"]
93+
deprecated_classes: list[str] = []
9794

9895
# external modules exposed in pandas namespace
9996
modules: list[str] = []

pandas/tests/apply/test_series_apply.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def test_apply_datetimetz():
186186
# change dtype
187187
# GH 14506 : Returned dtype changed from int32 to int64
188188
result = s.apply(lambda x: x.hour)
189-
exp = Series(list(range(24)) + [0], name="XX", dtype=np.int64)
189+
exp = Series(list(range(24)) + [0], name="XX", dtype=np.int32)
190190
tm.assert_series_equal(result, exp)
191191

192192
# not vectorized
@@ -766,7 +766,7 @@ def test_map_datetimetz():
766766
# change dtype
767767
# GH 14506 : Returned dtype changed from int32 to int64
768768
result = s.map(lambda x: x.hour)
769-
exp = Series(list(range(24)) + [0], name="XX", dtype=np.int64)
769+
exp = Series(list(range(24)) + [0], name="XX", dtype=np.int32)
770770
tm.assert_series_equal(result, exp)
771771

772772
# not vectorized

pandas/tests/base/test_unique.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55

66
import pandas as pd
77
import pandas._testing as tm
8-
from pandas.core.api import NumericIndex
8+
from pandas.core.api import (
9+
Float64Index,
10+
Int64Index,
11+
NumericIndex,
12+
UInt64Index,
13+
)
914
from pandas.tests.base.common import allow_na_ops
1015

1116

1217
def test_unique(index_or_series_obj):
1318
obj = index_or_series_obj
19+
if isinstance(obj, (Int64Index, UInt64Index, Float64Index)):
20+
pytest.skip("these indexes will be removed in followup")
1421
obj = np.repeat(obj, range(1, len(obj) + 1))
1522
result = obj.unique()
1623

@@ -36,6 +43,8 @@ def test_unique(index_or_series_obj):
3643
@pytest.mark.parametrize("null_obj", [np.nan, None])
3744
def test_unique_null(null_obj, index_or_series_obj):
3845
obj = index_or_series_obj
46+
if isinstance(obj, (Int64Index, UInt64Index, Float64Index)):
47+
pytest.skip("these indexes will be removed in followup")
3948

4049
if not allow_na_ops(obj):
4150
pytest.skip("type doesn't allow for NA operations")

pandas/tests/base/test_value_counts.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
def test_value_counts(index_or_series_obj):
2525
obj = index_or_series_obj
2626
obj = np.repeat(obj, range(1, len(obj) + 1))
27+
28+
if obj.dtype == np.float16:
29+
pytest.xfail("we don't have Float16Index, so value_counts is problematic")
30+
2731
result = obj.value_counts()
2832

2933
counter = collections.Counter(obj)
@@ -57,6 +61,9 @@ def test_value_counts_null(null_obj, index_or_series_obj):
5761
orig = index_or_series_obj
5862
obj = orig.copy()
5963

64+
if obj.dtype == np.float16:
65+
pytest.xfail("we don't have Float16Index, so value_counts is problematic")
66+
6067
if not allow_na_ops(obj):
6168
pytest.skip("type doesn't allow for NA operations")
6269
elif len(obj) < 1:

pandas/tests/frame/indexing/test_indexing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ def test_getitem_setitem_float_labels(self, using_array_manager):
736736

737737
# positional slicing only via iloc!
738738
msg = (
739-
"cannot do positional indexing on Float64Index with "
739+
"cannot do positional indexing on NumericIndex with "
740740
r"these indexers \[1.0\] of type float"
741741
)
742742
with pytest.raises(TypeError, match=msg):

pandas/tests/frame/methods/test_set_index.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def test_set_index_cast(self):
159159
df = DataFrame(
160160
{"A": [1.1, 2.2, 3.3], "B": [5.0, 6.1, 7.2]}, index=[2010, 2011, 2012]
161161
)
162-
df2 = df.set_index(df.index.astype(np.int32))
162+
df2 = df.set_index(df.index.astype(int))
163163
tm.assert_frame_equal(df, df2)
164164

165165
# A has duplicate values, C does not

pandas/tests/groupby/test_groupby.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def test_groupby_nonobject_dtype(mframe, df_mixed_floats):
9393
result = grouped.sum()
9494

9595
expected = mframe.groupby(key.astype("O")).sum()
96-
tm.assert_frame_equal(result, expected)
96+
tm.assert_frame_equal(result, expected, check_index_type=False)
9797

9898
# GH 3911, mixed frame non-conversion
9999
df = df_mixed_floats.copy()
@@ -228,6 +228,7 @@ def test_pass_args_kwargs_duplicate_columns(tsframe, as_index):
228228
2: tsframe[tsframe.index.month == 2].quantile(0.8),
229229
}
230230
expected = DataFrame(ex_data).T
231+
expected.index = Index(range(1, 3), dtype=np.int32)
231232
if not as_index:
232233
# TODO: try to get this more consistent?
233234
expected.index = Index(range(2))
@@ -2814,7 +2815,7 @@ def test_groupby_overflow(val, dtype):
28142815
result = df.groupby("a").sum()
28152816
expected = DataFrame(
28162817
{"b": [val * 2]},
2817-
index=Index([1], name="a", dtype=f"{dtype}64"),
2818+
index=Index([1], name="a", dtype=f"{dtype}8"),
28182819
dtype=f"{dtype}64",
28192820
)
28202821
tm.assert_frame_equal(result, expected)
@@ -2826,7 +2827,7 @@ def test_groupby_overflow(val, dtype):
28262827
result = df.groupby("a").prod()
28272828
expected = DataFrame(
28282829
{"b": [val * val]},
2829-
index=Index([1], name="a", dtype=f"{dtype}64"),
2830+
index=Index([1], name="a", dtype=f"{dtype}8"),
28302831
dtype=f"{dtype}64",
28312832
)
28322833
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)