Skip to content

Commit eafceae

Browse files
authored
PERF: sort_index with an already monotonic MultiIndex (#54883)
* PERF: sort_index with an already monotonic MultiIndex * whatsnew
1 parent e3e1325 commit eafceae

File tree

3 files changed

+17
-12
lines changed

3 files changed

+17
-12
lines changed

asv_bench/benchmarks/frame_methods.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -694,22 +694,28 @@ def time_frame_sort_values(self, ascending):
694694

695695

696696
class SortMultiKey:
697-
def setup(self):
697+
params = [True, False]
698+
param_names = ["monotonic"]
699+
700+
def setup(self, monotonic):
698701
N = 10000
699702
K = 10
700-
self.df_by_columns = DataFrame(
703+
df = DataFrame(
701704
{
702705
"key1": tm.makeStringIndex(N).values.repeat(K),
703706
"key2": tm.makeStringIndex(N).values.repeat(K),
704707
"value": np.random.randn(N * K),
705708
}
706709
)
707-
self.df_by_index = self.df_by_columns.set_index(["key1", "key2"])
710+
if monotonic:
711+
df = df.sort_values(["key1", "key2"])
712+
self.df_by_columns = df
713+
self.df_by_index = df.set_index(["key1", "key2"])
708714

709-
def time_sort_values(self):
715+
def time_sort_values(self, monotonic):
710716
self.df_by_columns.sort_values(by=["key1", "key2"])
711717

712-
def time_sort_index(self):
718+
def time_sort_index(self, monotonic):
713719
self.df_by_index.sort_index()
714720

715721

doc/source/whatsnew/v2.2.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Deprecations
157157

158158
Performance improvements
159159
~~~~~~~~~~~~~~~~~~~~~~~~
160-
- Performance improvement in :meth:`DataFrame.sort_index` and :meth:`Series.sort_index` when indexed by a :class:`MultiIndex` (:issue:`54835`)
160+
- Performance improvement in :meth:`DataFrame.sort_index` and :meth:`Series.sort_index` when indexed by a :class:`MultiIndex` (:issue:`54835`, :issue:`54883`)
161161
- Performance improvement when indexing with more than 4 keys (:issue:`54550`)
162162
-
163163

pandas/core/sorting.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,17 @@ def get_indexer_indexer(
9898
sort_remaining=sort_remaining,
9999
na_position=na_position,
100100
)
101+
elif (ascending and target.is_monotonic_increasing) or (
102+
not ascending and target.is_monotonic_decreasing
103+
):
104+
# Check monotonic-ness before sort an index (GH 11080)
105+
return None
101106
elif isinstance(target, ABCMultiIndex):
102107
codes = [lev.codes for lev in target._get_codes_for_sorting()]
103108
indexer = lexsort_indexer(
104109
codes, orders=ascending, na_position=na_position, codes_given=True
105110
)
106111
else:
107-
# Check monotonic-ness before sort an index (GH 11080)
108-
if (ascending and target.is_monotonic_increasing) or (
109-
not ascending and target.is_monotonic_decreasing
110-
):
111-
return None
112-
113112
# ascending can only be a Sequence for MultiIndex
114113
indexer = nargsort(
115114
target,

0 commit comments

Comments
 (0)