Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPR: remove Int/Uint/Float64Index from pandas/tests/indexes/ranges #50826

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 21 additions & 27 deletions pandas/core/indexes/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@
from pandas.core.construction import extract_array
import pandas.core.indexes.base as ibase
from pandas.core.indexes.base import maybe_extract_name
from pandas.core.indexes.numeric import (
Float64Index,
Int64Index,
NumericIndex,
)
from pandas.core.indexes.numeric import NumericIndex
from pandas.core.ops.common import unpack_zerodim_and_defer

if TYPE_CHECKING:
Expand All @@ -64,8 +60,8 @@ class RangeIndex(NumericIndex):
"""
Immutable Index implementing a monotonic integer range.

RangeIndex is a memory-saving special case of Int64Index limited to
representing monotonic ranges. Using RangeIndex may in some instances
RangeIndex is a memory-saving special case of an Index limited to representing
monotonic ranges with a 64-bit dtype. Using RangeIndex may in some instances
improve computing speed.

This is the default index type used
Expand Down Expand Up @@ -97,7 +93,6 @@ class RangeIndex(NumericIndex):
See Also
--------
Index : The base pandas Index type.
Int64Index : Index of int64 data.
"""

_typ = "rangeindex"
Expand Down Expand Up @@ -185,7 +180,7 @@ def _simple_new( # type: ignore[override]

# --------------------------------------------------------------------

# error: Return type "Type[Int64Index]" of "_constructor" incompatible with return
# error: Return type "Type[NumericIndex]" of "_constructor" incompatible with return
# type "Type[RangeIndex]" in supertype "Index"
@cache_readonly
def _constructor(self) -> type[NumericIndex]: # type: ignore[override]
Expand Down Expand Up @@ -331,7 +326,7 @@ def inferred_type(self) -> str:
# --------------------------------------------------------------------
# Indexing Methods

@doc(Int64Index.get_loc)
@doc(NumericIndex.get_loc)
def get_loc(self, key):
if is_integer(key) or (is_float(key) and key.is_integer()):
new_key = int(key)
Expand Down Expand Up @@ -377,32 +372,32 @@ def _get_indexer(
def tolist(self) -> list[int]:
return list(self._range)

@doc(Int64Index.__iter__)
@doc(NumericIndex.__iter__)
def __iter__(self) -> Iterator[int]:
yield from self._range

@doc(Int64Index._shallow_copy)
@doc(NumericIndex._shallow_copy)
def _shallow_copy(self, values, name: Hashable = no_default):
name = self.name if name is no_default else name

if values.dtype.kind == "f":
return Float64Index(values, name=name)
return NumericIndex(values, name=name, dtype=np.float64)
# GH 46675 & 43885: If values is equally spaced, return a
# more memory-compact RangeIndex instead of Int64Index
# more memory-compact RangeIndex instead of Index with 64-bit dtype
unique_diffs = unique_deltas(values)
if len(unique_diffs) == 1 and unique_diffs[0] != 0:
diff = unique_diffs[0]
new_range = range(values[0], values[-1] + diff, diff)
return type(self)._simple_new(new_range, name=name)
else:
return Int64Index._simple_new(values, name=name)
return NumericIndex._simple_new(values, name=name)

def _view(self: RangeIndex) -> RangeIndex:
result = type(self)._simple_new(self._range, name=self._name)
result._cache = self._cache
return result

@doc(Int64Index.copy)
@doc(NumericIndex.copy)
def copy(self, name: Hashable = None, deep: bool = False):
name = self._validate_names(name=name, deep=deep)[0]
new_index = self._rename(name=name)
Expand Down Expand Up @@ -517,7 +512,6 @@ def _intersection(self, other: Index, sort: bool = False):
# caller is responsible for checking self and other are both non-empty

if not isinstance(other, RangeIndex):
# Int64Index
return super()._intersection(other, sort=sort)

first = self._range[::-1] if self.step < 0 else self._range
Expand Down Expand Up @@ -604,10 +598,10 @@ def _union(self, other: Index, sort):
sort : False or None, default None
Whether to sort (monotonically increasing) the resulting index.
``sort=None`` returns a ``RangeIndex`` if possible or a sorted
``Int64Index`` if not.
``Index`` with a int64 dtype if not.
``sort=False`` can return a ``RangeIndex`` if self is monotonically
increasing and other is fully contained in self. Otherwise, returns
an unsorted ``Int64Index``
an unsorted ``Index`` with an int64 dtype.

Returns
-------
Expand Down Expand Up @@ -819,9 +813,9 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
Overriding parent method for the case of all RangeIndex instances.

When all members of "indexes" are of type RangeIndex: result will be
RangeIndex if possible, Int64Index otherwise. E.g.:
RangeIndex if possible, Index with a int64 dtype otherwise. E.g.:
indexes = [RangeIndex(3), RangeIndex(3, 6)] -> RangeIndex(6)
indexes = [RangeIndex(3), RangeIndex(4, 6)] -> Int64Index([0,1,2,4,5])
indexes = [RangeIndex(3), RangeIndex(4, 6)] -> Index([0,1,2,4,5], dtype='int64')
"""
if not all(isinstance(x, RangeIndex) for x in indexes):
return super()._concat(indexes, name)
Expand All @@ -848,7 +842,7 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
# First non-empty index had only one element
if rng.start == start:
values = np.concatenate([x._values for x in rng_indexes])
result = Int64Index(values)
result = self._constructor(values)
return result.rename(name)

step = rng.start - start
Expand All @@ -857,7 +851,9 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
next_ is not None and rng.start != next_
)
if non_consecutive:
result = Int64Index(np.concatenate([x._values for x in rng_indexes]))
result = self._constructor(
np.concatenate([x._values for x in rng_indexes])
)
return result.rename(name)

if step is not None:
Expand Down Expand Up @@ -905,7 +901,6 @@ def __getitem__(self, key):
"and integer or boolean "
"arrays are valid indices"
)
# fall back to Int64Index
return super().__getitem__(key)

def _getitem_slice(self: RangeIndex, slobj: slice) -> RangeIndex:
Expand Down Expand Up @@ -1010,15 +1005,14 @@ def _arith_method(self, other, op):
res_name = ops.get_op_result_name(self, other)
result = type(self)(rstart, rstop, rstep, name=res_name)

# for compat with numpy / Int64Index
# for compat with numpy / Index with int64 dtype
# even if we can represent as a RangeIndex, return
# as a Float64Index if we have float-like descriptors
# as a float64 Index if we have float-like descriptors
if not all(is_integer(x) for x in [rstart, rstop, rstep]):
result = result.astype("float64")

return result

except (ValueError, TypeError, ZeroDivisionError):
# Defer to Int64Index implementation
# test_arithmetic_explicit_conversions
return super()._arith_method(other, op)
33 changes: 17 additions & 16 deletions pandas/tests/indexes/ranges/test_join.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import numpy as np

from pandas.core.dtypes.common import is_int64_dtype

from pandas import (
Index,
RangeIndex,
)
import pandas._testing as tm
from pandas.core.indexes.api import Int64Index


class TestJoin:
def test_join_outer(self):
# join with Int64Index
# join with Index[int64]
index = RangeIndex(start=0, stop=20, step=2)
other = Int64Index(np.arange(25, 14, -1))
other = Index(np.arange(25, 14, -1, dtype=np.int64))

res, lidx, ridx = index.join(other, how="outer", return_indexers=True)
noidx_res = index.join(other, how="outer")
tm.assert_index_equal(res, noidx_res)

eres = Int64Index(
eres = Index(
[0, 2, 4, 6, 8, 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
)
elidx = np.array(
Expand All @@ -30,9 +31,9 @@ def test_join_outer(self):
dtype=np.intp,
)

assert isinstance(res, Int64Index)
assert isinstance(res, Index) and is_int64_dtype(res.dtype)
assert not isinstance(res, RangeIndex)
tm.assert_index_equal(res, eres)
tm.assert_index_equal(res, eres, exact=True)
tm.assert_numpy_array_equal(lidx, elidx)
tm.assert_numpy_array_equal(ridx, eridx)

Expand All @@ -43,7 +44,7 @@ def test_join_outer(self):
noidx_res = index.join(other, how="outer")
tm.assert_index_equal(res, noidx_res)

assert isinstance(res, Int64Index)
assert isinstance(res, Index) and res.dtype == np.int64
assert not isinstance(res, RangeIndex)
tm.assert_index_equal(res, eres)
tm.assert_numpy_array_equal(lidx, elidx)
Expand All @@ -52,7 +53,7 @@ def test_join_outer(self):
def test_join_inner(self):
# Join with non-RangeIndex
index = RangeIndex(start=0, stop=20, step=2)
other = Int64Index(np.arange(25, 14, -1))
other = Index(np.arange(25, 14, -1, dtype=np.int64))

res, lidx, ridx = index.join(other, how="inner", return_indexers=True)

Expand All @@ -62,7 +63,7 @@ def test_join_inner(self):
lidx = lidx.take(ind)
ridx = ridx.take(ind)

eres = Int64Index([16, 18])
eres = Index([16, 18])
elidx = np.array([8, 9], dtype=np.intp)
eridx = np.array([9, 7], dtype=np.intp)

Expand All @@ -82,9 +83,9 @@ def test_join_inner(self):
tm.assert_numpy_array_equal(ridx, eridx)

def test_join_left(self):
# Join with Int64Index
# Join with Index[int64]
index = RangeIndex(start=0, stop=20, step=2)
other = Int64Index(np.arange(25, 14, -1))
other = Index(np.arange(25, 14, -1, dtype=np.int64))

res, lidx, ridx = index.join(other, how="left", return_indexers=True)
eres = index
Expand All @@ -96,7 +97,7 @@ def test_join_left(self):
tm.assert_numpy_array_equal(ridx, eridx)

# Join withRangeIndex
other = Int64Index(np.arange(25, 14, -1))
other = Index(np.arange(25, 14, -1, dtype=np.int64))

res, lidx, ridx = index.join(other, how="left", return_indexers=True)

Expand All @@ -106,15 +107,15 @@ def test_join_left(self):
tm.assert_numpy_array_equal(ridx, eridx)

def test_join_right(self):
# Join with Int64Index
# Join with Index[int64]
index = RangeIndex(start=0, stop=20, step=2)
other = Int64Index(np.arange(25, 14, -1))
other = Index(np.arange(25, 14, -1, dtype=np.int64))

res, lidx, ridx = index.join(other, how="right", return_indexers=True)
eres = other
elidx = np.array([-1, -1, -1, -1, -1, -1, -1, 9, -1, 8, -1], dtype=np.intp)

assert isinstance(other, Int64Index)
assert isinstance(other, Index) and other.dtype == np.int64
tm.assert_index_equal(res, eres)
tm.assert_numpy_array_equal(lidx, elidx)
assert ridx is None
Expand Down Expand Up @@ -164,7 +165,7 @@ def test_join_non_unique(self):

res, lidx, ridx = index.join(other, return_indexers=True)

eres = Int64Index([0, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18])
eres = Index([0, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18])
elidx = np.array([0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9], dtype=np.intp)
eridx = np.array([-1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1], dtype=np.intp)

Expand Down
27 changes: 11 additions & 16 deletions pandas/tests/indexes/ranges/test_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@
from pandas.core.dtypes.common import ensure_platform_int

import pandas as pd
import pandas._testing as tm
from pandas.core.indexes.api import (
Float64Index,
from pandas import (
Index,
Int64Index,
RangeIndex,
)
import pandas._testing as tm
from pandas.tests.indexes.common import NumericBase

# aliases to make some tests easier to read
RI = RangeIndex
I64 = Int64Index
F64 = Float64Index
OI = Index


class TestRangeIndex(NumericBase):
Expand Down Expand Up @@ -111,7 +106,7 @@ def test_insert(self):
tm.assert_index_equal(idx[0:4], result.insert(0, idx[0]), exact="equiv")

# GH 18295 (test missing)
expected = Float64Index([0, np.nan, 1, 2, 3, 4])
expected = Index([0, np.nan, 1, 2, 3, 4], dtype=np.float64)
for na in [np.nan, None, pd.NA]:
result = RangeIndex(5).insert(1, na)
tm.assert_index_equal(result, expected)
Expand Down Expand Up @@ -379,7 +374,7 @@ def test_nbytes(self):

# memory savings vs int index
idx = RangeIndex(0, 1000)
assert idx.nbytes < Int64Index(idx._values).nbytes / 10
assert idx.nbytes < Index(idx._values).nbytes / 10

# constant memory usage
i2 = RangeIndex(0, 10)
Expand Down Expand Up @@ -530,16 +525,16 @@ def test_len_specialised(self, step):
([RI(-4, -8), RI(-8, -12)], RI(0, 0)),
([RI(-4, -8), RI(3, -4)], RI(0, 0)),
([RI(-4, -8), RI(3, 5)], RI(3, 5)),
([RI(-4, -2), RI(3, 5)], I64([-4, -3, 3, 4])),
([RI(-4, -2), RI(3, 5)], Index([-4, -3, 3, 4])),
([RI(-2), RI(3, 5)], RI(3, 5)),
([RI(2), RI(2)], I64([0, 1, 0, 1])),
([RI(2), RI(2)], Index([0, 1, 0, 1])),
([RI(2), RI(2, 5), RI(5, 8, 4)], RI(0, 6)),
([RI(2), RI(3, 5), RI(5, 8, 4)], I64([0, 1, 3, 4, 5])),
([RI(2), RI(3, 5), RI(5, 8, 4)], Index([0, 1, 3, 4, 5])),
([RI(-2, 2), RI(2, 5), RI(5, 8, 4)], RI(-2, 6)),
([RI(3), OI([-1, 3, 15])], OI([0, 1, 2, -1, 3, 15])),
([RI(3), OI([-1, 3.1, 15.0])], OI([0, 1, 2, -1, 3.1, 15.0])),
([RI(3), OI(["a", None, 14])], OI([0, 1, 2, "a", None, 14])),
([RI(3, 1), OI(["a", None, 14])], OI(["a", None, 14])),
([RI(3), Index([-1, 3, 15])], Index([0, 1, 2, -1, 3, 15])),
([RI(3), Index([-1, 3.1, 15.0])], Index([0, 1, 2, -1, 3.1, 15.0])),
([RI(3), Index(["a", None, 14])], Index([0, 1, 2, "a", None, 14])),
([RI(3, 1), Index(["a", None, 14])], Index(["a", None, 14])),
]
)
def appends(self, request):
Expand Down
Loading