Skip to content

Commit 6d4aea9

Browse files
author
tp
committed
imroved performance of CategoricalIndex.is_monotonic*
1 parent a5c02d5 commit 6d4aea9

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

asv_bench/benchmarks/categoricals.py

+20
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,23 @@ def setup(self, dtype):
169169

170170
def time_isin_categorical(self, dtype):
171171
self.series.isin(self.sample)
172+
173+
174+
class IsMonotonic(object):
175+
176+
def setup(self):
177+
N = 1000
178+
self.c = pd.CategoricalIndex(list('a'*N + 'b'*N + 'c'*N))
179+
self.s = pd.Series(self.c)
180+
181+
def time_categorical_index_is_monotonic_increasing(self):
182+
self.c.is_monotonic_increasing
183+
184+
def time_categorical_index_is_monotonic_decreasing(self):
185+
self.c.is_monotonic_decreasing
186+
187+
def time_categorical_series_is_monotonic_increasing(self):
188+
self.s.is_monotonic_increasing
189+
190+
def time_categorical_series_is_monotonic_decreasing(self):
191+
self.s.is_monotonic_decreasing

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ Performance Improvements
10791079
- Improved performance of :func:`pandas.core.groupby.GroupBy.pct_change` (:issue:`19165`)
10801080
- Improved performance of :func:`Series.isin` in the case of categorical dtypes (:issue:`20003`)
10811081
- Improved performance of ``getattr(Series, attr)`` when the Series has certain index types. This manifiested in slow printing of large Series with a ``DatetimeIndex`` (:issue:`19764`)
1082+
- Improved performance of :meth:`CategoricalIndex.is_monotonic_increasing`, :meth:`CategoricalIndex.is_monotonic_decreasing` and :meth:`CategoricalIndex.is_monotonic` (:issue:`21025`)
10821083
- Fixed a performance regression for :func:`GroupBy.nth` and :func:`GroupBy.last` with some object columns (:issue:`19283`)
10831084

10841085
.. _whatsnew_0230.docs:

pandas/core/indexes/category.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,11 @@ def is_unique(self):
382382

383383
@property
384384
def is_monotonic_increasing(self):
385-
return Index(self.codes).is_monotonic_increasing
385+
return self._engine.is_monotonic_increasing
386386

387387
@property
388388
def is_monotonic_decreasing(self):
389-
return Index(self.codes).is_monotonic_decreasing
389+
return self._engine.is_monotonic_decreasing
390390

391391
@Appender(_index_shared_docs['index_unique'] % _index_doc_kwargs)
392392
def unique(self, level=None):

pandas/tests/indexes/test_category.py

+17-11
Original file line numberDiff line numberDiff line change
@@ -543,35 +543,41 @@ def test_reindex_empty_index(self):
543543
tm.assert_numpy_array_equal(indexer,
544544
np.array([-1, -1], dtype=np.intp))
545545

546-
def test_is_monotonic(self):
547-
c = CategoricalIndex([1, 2, 3])
546+
@pytest.mark.parametrize('data, non_lexsorted_data', [
547+
[[1, 2, 3], [9, 0, 1, 2, 3]],
548+
[list('abc'), list('fabcd')],
549+
])
550+
def test_is_monotonic(self, data, non_lexsorted_data):
551+
c = CategoricalIndex(data)
548552
assert c.is_monotonic_increasing
549553
assert not c.is_monotonic_decreasing
550554

551-
c = CategoricalIndex([1, 2, 3], ordered=True)
555+
c = CategoricalIndex(data, ordered=True)
552556
assert c.is_monotonic_increasing
553557
assert not c.is_monotonic_decreasing
554558

555-
c = CategoricalIndex([1, 2, 3], categories=[3, 2, 1])
559+
c = CategoricalIndex(data, categories=reversed(data))
556560
assert not c.is_monotonic_increasing
557561
assert c.is_monotonic_decreasing
558562

559-
c = CategoricalIndex([1, 3, 2], categories=[3, 2, 1])
563+
c = CategoricalIndex(data, categories=reversed(data), ordered=True)
560564
assert not c.is_monotonic_increasing
561-
assert not c.is_monotonic_decreasing
565+
assert c.is_monotonic_decreasing
562566

563-
c = CategoricalIndex([1, 2, 3], categories=[3, 2, 1], ordered=True)
567+
# test when data is neither monotonic increasing nor decreasing
568+
reordered_data = [data[0], data[2], data[1]]
569+
c = CategoricalIndex(reordered_data, categories=reversed(data))
564570
assert not c.is_monotonic_increasing
565-
assert c.is_monotonic_decreasing
571+
assert not c.is_monotonic_decreasing
566572

567573
# non lexsorted categories
568-
categories = [9, 0, 1, 2, 3]
574+
categories = non_lexsorted_data
569575

570-
c = CategoricalIndex([9, 0], categories=categories)
576+
c = CategoricalIndex(categories[:2], categories=categories)
571577
assert c.is_monotonic_increasing
572578
assert not c.is_monotonic_decreasing
573579

574-
c = CategoricalIndex([0, 1], categories=categories)
580+
c = CategoricalIndex(categories[1:3], categories=categories)
575581
assert c.is_monotonic_increasing
576582
assert not c.is_monotonic_decreasing
577583

0 commit comments

Comments
 (0)