Skip to content

Commit 4a9efba

Browse files
mroeschkepmhatre1
authored andcommitted
PERF: RangeIndex.append with the same index (pandas-dev#57252)
1 parent 052c775 commit 4a9efba

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

asv_bench/benchmarks/index_object.py

+4
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,14 @@ def setup(self):
136136
self.int_idxs.append(i_idx)
137137
o_idx = i_idx.astype(str)
138138
self.object_idxs.append(o_idx)
139+
self.same_range_idx = [self.range_idx] * N
139140

140141
def time_append_range_list(self):
141142
self.range_idx.append(self.range_idxs)
142143

144+
def time_append_range_list_same(self):
145+
self.range_idx.append(self.same_range_idx)
146+
143147
def time_append_int_list(self):
144148
self.int_idx.append(self.int_idxs)
145149

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ Performance improvements
132132
- Performance improvement in :meth:`Index.join` by propagating cached attributes in cases where the result matches one of the inputs (:issue:`57023`)
133133
- Performance improvement in :meth:`Index.take` when ``indices`` is a full range indexer from zero to length of index (:issue:`56806`)
134134
- Performance improvement in :meth:`MultiIndex.equals` for equal length indexes (:issue:`56990`)
135+
- Performance improvement in :meth:`RangeIndex.append` when appending the same index (:issue:`57252`)
135136
- Performance improvement in indexing operations for string dtypes (:issue:`56997`)
136137
-
137138

pandas/core/indexes/range.py

+24-5
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,17 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
955955
start = step = next_ = None
956956

957957
# Filter the empty indexes
958-
non_empty_indexes = [obj for obj in rng_indexes if len(obj)]
958+
non_empty_indexes = []
959+
all_same_index = True
960+
prev: RangeIndex | None = None
961+
for obj in rng_indexes:
962+
if len(obj):
963+
non_empty_indexes.append(obj)
964+
if all_same_index:
965+
if prev is not None:
966+
all_same_index = prev.equals(obj)
967+
else:
968+
prev = obj
959969

960970
for obj in non_empty_indexes:
961971
rng = obj._range
@@ -968,7 +978,12 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
968978
elif step is None:
969979
# First non-empty index had only one element
970980
if rng.start == start:
971-
values = np.concatenate([x._values for x in rng_indexes])
981+
if all_same_index:
982+
values = np.tile(
983+
non_empty_indexes[0]._values, len(non_empty_indexes)
984+
)
985+
else:
986+
values = np.concatenate([x._values for x in rng_indexes])
972987
result = self._constructor(values)
973988
return result.rename(name)
974989

@@ -978,9 +993,13 @@ def _concat(self, indexes: list[Index], name: Hashable) -> Index:
978993
next_ is not None and rng.start != next_
979994
)
980995
if non_consecutive:
981-
result = self._constructor(
982-
np.concatenate([x._values for x in rng_indexes])
983-
)
996+
if all_same_index:
997+
values = np.tile(
998+
non_empty_indexes[0]._values, len(non_empty_indexes)
999+
)
1000+
else:
1001+
values = np.concatenate([x._values for x in rng_indexes])
1002+
result = self._constructor(values)
9841003
return result.rename(name)
9851004

9861005
if step is not None:

0 commit comments

Comments
 (0)