Skip to content

Commit d45b8ef

Browse files
mroeschkepmhatre1
authored andcommitted
PERF: Return RangeIndex from RangeIndex.reindex when possible (pandas-dev#57647)
* PERF: Return RangeIndex from RangeIndex.reindex when possible * Add whatsnew number * Only if index * add name * Skip for type self, undo test * Use intp * merge * Add test for Index return
1 parent 4c01d71 commit d45b8ef

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ Performance improvements
256256
- Performance improvement in :meth:`RangeIndex.__getitem__` with a boolean mask returning a :class:`RangeIndex` instead of a :class:`Index` when possible. (:issue:`57588`)
257257
- Performance improvement in :meth:`RangeIndex.append` when appending the same index (:issue:`57252`)
258258
- Performance improvement in :meth:`RangeIndex.join` returning a :class:`RangeIndex` instead of a :class:`Index` when possible. (:issue:`57651`)
259+
- Performance improvement in :meth:`RangeIndex.reindex` returning a :class:`RangeIndex` instead of a :class:`Index` when possible. (:issue:`57647`)
259260
- Performance improvement in :meth:`RangeIndex.take` returning a :class:`RangeIndex` instead of a :class:`Index` when possible. (:issue:`57445`)
260261
- Performance improvement in ``DataFrameGroupBy.__len__`` and ``SeriesGroupBy.__len__`` (:issue:`57595`)
261262
- Performance improvement in indexing operations for string dtypes (:issue:`56997`)

pandas/core/indexes/range.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
doc,
3030
)
3131

32+
from pandas.core.dtypes import missing
3233
from pandas.core.dtypes.base import ExtensionDtype
3334
from pandas.core.dtypes.common import (
3435
ensure_platform_int,
@@ -475,7 +476,7 @@ def _shallow_copy(self, values, name: Hashable = no_default):
475476
# GH 46675 & 43885: If values is equally spaced, return a
476477
# more memory-compact RangeIndex instead of Index with 64-bit dtype
477478
diff = values[1] - values[0]
478-
if diff != 0:
479+
if not missing.isna(diff) and diff != 0:
479480
maybe_range_indexer, remainder = np.divmod(values - values[0], diff)
480481
if (
481482
lib.is_range_indexer(maybe_range_indexer, len(maybe_range_indexer))
@@ -490,6 +491,11 @@ def _view(self) -> Self:
490491
result._cache = self._cache
491492
return result
492493

494+
def _wrap_reindex_result(self, target, indexer, preserve_names: bool):
495+
if not isinstance(target, type(self)) and target.dtype.kind == "i":
496+
target = self._shallow_copy(target._values, name=target.name)
497+
return super()._wrap_reindex_result(target, indexer, preserve_names)
498+
493499
@doc(Index.copy)
494500
def copy(self, name: Hashable | None = None, deep: bool = False) -> Self:
495501
name = self._validate_names(name=name, deep=deep)[0]

pandas/tests/indexes/ranges/test_range.py

+20
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,26 @@ def test_range_index_rsub_by_const(self):
608608
tm.assert_index_equal(result, expected)
609609

610610

611+
def test_reindex_returns_rangeindex():
612+
ri = RangeIndex(2, name="foo")
613+
result, result_indexer = ri.reindex([1, 2, 3])
614+
expected = RangeIndex(1, 4, name="foo")
615+
tm.assert_index_equal(result, expected, exact=True)
616+
617+
expected_indexer = np.array([1, -1, -1], dtype=np.intp)
618+
tm.assert_numpy_array_equal(result_indexer, expected_indexer)
619+
620+
621+
def test_reindex_returns_index():
622+
ri = RangeIndex(4, name="foo")
623+
result, result_indexer = ri.reindex([0, 1, 3])
624+
expected = Index([0, 1, 3], name="foo")
625+
tm.assert_index_equal(result, expected, exact=True)
626+
627+
expected_indexer = np.array([0, 1, 3], dtype=np.intp)
628+
tm.assert_numpy_array_equal(result_indexer, expected_indexer)
629+
630+
611631
def test_take_return_rangeindex():
612632
ri = RangeIndex(5, name="foo")
613633
result = ri.take([])

pandas/tests/indexing/test_loc.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1204,10 +1204,7 @@ def test_loc_setitem_empty_append_raises(self):
12041204
data = [1, 2]
12051205
df = DataFrame(columns=["x", "y"])
12061206
df.index = df.index.astype(np.int64)
1207-
msg = (
1208-
rf"None of \[Index\(\[0, 1\], dtype='{np.dtype(int)}'\)\] "
1209-
r"are in the \[index\]"
1210-
)
1207+
msg = r"None of .*Index.* are in the \[index\]"
12111208
with pytest.raises(KeyError, match=msg):
12121209
df.loc[[0, 1], "x"] = data
12131210

0 commit comments

Comments
 (0)