Skip to content

Commit c8a4567

Browse files
mroeschkepmhatre1
authored andcommitted
PERF: Avoid np.divmod in maybe_sequence_to_range (pandas-dev#57812)
* PERF: Avoid np.divmod in RangeIndex._shallow_copy * Make is_range * pyi error * Use step * Switch back to int6432 * try int64_t * Revert "try int64_t" This reverts commit b8ea98c. * Adjust maybe_sequence_to_range * Access first element once
1 parent af8f8f8 commit c8a4567

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

pandas/_libs/lib.pyi

+4
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,7 @@ def is_range_indexer(
231231
left: np.ndarray,
232232
n: int, # np.ndarray[np.int64, ndim=1]
233233
) -> bool: ...
234+
def is_sequence_range(
235+
sequence: np.ndarray,
236+
step: int, # np.ndarray[np.int64, ndim=1]
237+
) -> bool: ...

pandas/_libs/lib.pyx

+22
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,28 @@ def is_range_indexer(ndarray[int6432_t, ndim=1] left, Py_ssize_t n) -> bool:
678678
return True
679679

680680

681+
@cython.wraparound(False)
682+
@cython.boundscheck(False)
683+
def is_sequence_range(ndarray[int6432_t, ndim=1] sequence, int64_t step) -> bool:
684+
"""
685+
Check if sequence is equivalent to a range with the specified step.
686+
"""
687+
cdef:
688+
Py_ssize_t i, n = len(sequence)
689+
int6432_t first_element
690+
691+
if step == 0:
692+
return False
693+
if n == 0:
694+
return True
695+
696+
first_element = sequence[0]
697+
for i in range(1, n):
698+
if sequence[i] != first_element + i * step:
699+
return False
700+
return True
701+
702+
681703
ctypedef fused ndarr_object:
682704
ndarray[object, ndim=1]
683705
ndarray[object, ndim=2]

pandas/core/indexes/base.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -7150,7 +7150,7 @@ def maybe_sequence_to_range(sequence) -> Any | range:
71507150
-------
71517151
Any : input or range
71527152
"""
7153-
if isinstance(sequence, (ABCSeries, Index)):
7153+
if isinstance(sequence, (ABCSeries, Index, range)):
71547154
return sequence
71557155
np_sequence = np.asarray(sequence)
71567156
if np_sequence.dtype.kind != "i" or len(np_sequence) == 1:
@@ -7160,13 +7160,7 @@ def maybe_sequence_to_range(sequence) -> Any | range:
71607160
diff = np_sequence[1] - np_sequence[0]
71617161
if diff == 0:
71627162
return sequence
7163-
elif len(np_sequence) == 2:
7164-
return range(np_sequence[0], np_sequence[1] + diff, diff)
7165-
maybe_range_indexer, remainder = np.divmod(np_sequence - np_sequence[0], diff)
7166-
if (
7167-
lib.is_range_indexer(maybe_range_indexer, len(maybe_range_indexer))
7168-
and not remainder.any()
7169-
):
7163+
elif len(np_sequence) == 2 or lib.is_sequence_range(np_sequence, diff):
71707164
return range(np_sequence[0], np_sequence[-1] + diff, diff)
71717165
else:
71727166
return sequence

0 commit comments

Comments
 (0)