Skip to content

Commit e056b3a

Browse files
committed
PERF: rework MultiIndex.is_monotonic as per @ssanderson idea
1 parent c8563a6 commit e056b3a

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

asv_bench/benchmarks/indexing.py

+3
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ def time_multiindex_get_indexer(self):
204204
self.miint.get_indexer(np.array([(0, 10), (0, 11), (0, 12), (0, 13), (0, 14),
205205
(0, 15), (0, 16),(0, 17), (0, 18), (0, 19)], dtype=object))
206206

207+
def time_is_monotonic(self):
208+
self.miint.is_monotonic
209+
207210

208211
class PanelIndexing(object):
209212
goal_time = 0.2

pandas/indexes/multi.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -667,15 +667,21 @@ def _has_complex_internals(self):
667667
@cache_readonly
668668
def is_monotonic(self):
669669

670-
# TODO
671-
# this is unfortunate we end up tupelizing
672-
# just to determine monotonicity :<
673-
674-
# fast-path
675-
if not self.levels[0].is_monotonic:
676-
return False
670+
def level_values(level):
671+
unique = self.levels[level]
672+
labels = self.labels[level]
673+
return algos.take_1d(unique.values, labels,
674+
fill_value=unique._na_value)
675+
676+
# reversed() because lexsort() wants the most significant key last.
677+
values = [level_values(i) for i in reversed(range(len(self.levels)))]
678+
try:
679+
sort_order = np.lexsort(values)
680+
return Index(sort_order).is_monotonic
681+
except TypeError:
677682

678-
return Index(self.values).is_monotonic
683+
# we have mixed types and np.lexsort is not happy
684+
return Index(self.values).is_monotonic
679685

680686
@cache_readonly
681687
def is_unique(self):

0 commit comments

Comments
 (0)