Skip to content

Commit ebcb0c0

Browse files
committed
ENH: Implement strictly monotonic methods
Simply checks if the index is monotonic and unique.
1 parent 8447d52 commit ebcb0c0

File tree

6 files changed

+82
-8
lines changed

6 files changed

+82
-8
lines changed

doc/source/api.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,8 @@ Attributes
12851285
Index.is_monotonic
12861286
Index.is_monotonic_increasing
12871287
Index.is_monotonic_decreasing
1288+
Index.is_strictly_monotonic_increasing
1289+
Index.is_strictly_monotonic_decreasing
12881290
Index.is_unique
12891291
Index.has_duplicates
12901292
Index.dtype

pandas/core/indexes/base.py

+18
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,15 @@ def is_monotonic_increasing(self):
11911191
"""
11921192
return if the index is monotonic increasing (only equal or
11931193
increasing) values.
1194+
1195+
Examples
1196+
--------
1197+
>>> Index([1, 2, 3]).is_monotonic_increasing
1198+
True
1199+
>>> Index([1, 2, 2]).is_monotonic_increasing
1200+
True
1201+
>>> Index([1, 3, 2]).is_monotonic_increasing
1202+
False
11941203
"""
11951204
return self._engine.is_monotonic_increasing
11961205

@@ -1199,6 +1208,15 @@ def is_monotonic_decreasing(self):
11991208
"""
12001209
return if the index is monotonic decreasing (only equal or
12011210
decreasing) values.
1211+
1212+
Examples
1213+
--------
1214+
>>> Index([3, 2, 1]).is_monotonic_decreasing
1215+
True
1216+
>>> Index([3, 2, 2]).is_monotonic_decreasing
1217+
True
1218+
>>> Index([3, 1, 2]).is_monotonic_decreasing
1219+
False
12021220
"""
12031221
return self._engine.is_monotonic_decreasing
12041222

pandas/tests/indexes/test_base.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1330,8 +1330,10 @@ def test_tuple_union_bug(self):
13301330

13311331
def test_is_monotonic_incomparable(self):
13321332
index = Index([5, datetime.now(), 7])
1333-
assert not index.is_monotonic
1333+
assert not index.is_monotonic_increasing
13341334
assert not index.is_monotonic_decreasing
1335+
assert not index.is_strictly_monotonic_increasing
1336+
assert not index.is_strictly_monotonic_decreasing
13351337

13361338
def test_get_set_value(self):
13371339
values = np.random.randn(100)
@@ -2030,6 +2032,8 @@ def test_is_monotonic_na(self):
20302032
for index in examples:
20312033
assert not index.is_monotonic_increasing
20322034
assert not index.is_monotonic_decreasing
2035+
assert not index.is_strictly_monotonic_increasing
2036+
assert not index.is_strictly_monotonic_decreasing
20332037

20342038
def test_repr_summary(self):
20352039
with cf.option_context('display.max_seq_items', 10):

pandas/tests/indexes/test_multi.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -2373,22 +2373,30 @@ def test_is_monotonic(self):
23732373
i = MultiIndex.from_product([np.arange(10),
23742374
np.arange(10)], names=['one', 'two'])
23752375
assert i.is_monotonic
2376+
assert i.is_strictly_monotonic_increasing
23762377
assert Index(i.values).is_monotonic
2378+
assert i.is_strictly_monotonic_increasing
23772379

23782380
i = MultiIndex.from_product([np.arange(10, 0, -1),
23792381
np.arange(10)], names=['one', 'two'])
23802382
assert not i.is_monotonic
2383+
assert not i.is_strictly_monotonic_increasing
23812384
assert not Index(i.values).is_monotonic
2385+
assert not Index(i.values).is_strictly_monotonic_increasing
23822386

23832387
i = MultiIndex.from_product([np.arange(10),
23842388
np.arange(10, 0, -1)],
23852389
names=['one', 'two'])
23862390
assert not i.is_monotonic
2391+
assert not i.is_strictly_monotonic_increasing
23872392
assert not Index(i.values).is_monotonic
2393+
assert not Index(i.values).is_strictly_monotonic_increasing
23882394

23892395
i = MultiIndex.from_product([[1.0, np.nan, 2.0], ['a', 'b', 'c']])
23902396
assert not i.is_monotonic
2397+
assert not i.is_strictly_monotonic_increasing
23912398
assert not Index(i.values).is_monotonic
2399+
assert not Index(i.values).is_strictly_monotonic_increasing
23922400

23932401
# string ordering
23942402
i = MultiIndex(levels=[['foo', 'bar', 'baz', 'qux'],
@@ -2397,15 +2405,17 @@ def test_is_monotonic(self):
23972405
[0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
23982406
names=['first', 'second'])
23992407
assert not i.is_monotonic
2400-
assert not Index(i.values).is_monotonic
2408+
assert not i.is_strictly_monotonic_increasing
2409+
assert not Index(i.values).is_strictly_monotonic_increasing
24012410

24022411
i = MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'],
24032412
['mom', 'next', 'zenith']],
24042413
labels=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3],
24052414
[0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
24062415
names=['first', 'second'])
24072416
assert i.is_monotonic
2408-
assert Index(i.values).is_monotonic
2417+
assert i.is_strictly_monotonic_increasing
2418+
assert Index(i.values).is_strictly_monotonic_increasing
24092419

24102420
# mixed levels, hits the TypeError
24112421
i = MultiIndex(
@@ -2416,6 +2426,20 @@ def test_is_monotonic(self):
24162426
names=['household_id', 'asset_id'])
24172427

24182428
assert not i.is_monotonic
2429+
assert not i.is_strictly_monotonic_increasing
2430+
2431+
def test_is_strictly_monotonic(self):
2432+
idx = pd.MultiIndex(levels=[['bar', 'baz'], ['mom', 'next']],
2433+
labels=[[0, 0, 1, 1], [0, 0, 0, 1]])
2434+
assert idx.is_monotonic_increasing
2435+
assert not idx.is_strictly_monotonic_increasing
2436+
2437+
@pytest.mark.xfail(reason="buggy MultiIndex.is_monotonic_decresaing.")
2438+
def test_is_strictly_monotonic_decreasing(self):
2439+
idx = pd.MultiIndex(levels=[['baz', 'bar'], ['next', 'mom']],
2440+
labels=[[0, 0, 1, 1], [0, 0, 0, 1]])
2441+
assert idx.is_monotonic_decreasing
2442+
assert not idx.is_strictly_monotonic_decreasing
24192443

24202444
def test_reconstruct_sort(self):
24212445

pandas/tests/indexes/test_numeric.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -465,16 +465,36 @@ def test_view(self):
465465
def test_is_monotonic(self):
466466
assert self.index.is_monotonic
467467
assert self.index.is_monotonic_increasing
468+
assert self.index.is_strictly_monotonic_increasing
468469
assert not self.index.is_monotonic_decreasing
470+
assert not self.index.is_strictly_monotonic_decreasing
469471

470472
index = self._holder([4, 3, 2, 1])
471473
assert not index.is_monotonic
472-
assert index.is_monotonic_decreasing
474+
assert not index.is_strictly_monotonic_increasing
475+
assert index.is_strictly_monotonic_decreasing
473476

474477
index = self._holder([1])
475478
assert index.is_monotonic
476479
assert index.is_monotonic_increasing
477480
assert index.is_monotonic_decreasing
481+
assert index.is_strictly_monotonic_increasing
482+
assert index.is_strictly_monotonic_decreasing
483+
484+
def test_is_strictly_monotonic(self):
485+
index = self._holder([1, 1, 2, 3])
486+
assert index.is_monotonic_increasing
487+
assert not index.is_strictly_monotonic_increasing
488+
489+
index = self._holder([3, 2, 1, 1])
490+
assert index.is_monotonic_decreasing
491+
assert not index.is_strictly_monotonic_decreasing
492+
493+
index = self._holder([1, 1])
494+
assert index.is_monotonic_increasing
495+
assert index.is_monotonic_decreasing
496+
assert not index.is_strictly_monotonic_increasing
497+
assert not index.is_strictly_monotonic_decreasing
478498

479499
def test_logical_compat(self):
480500
idx = self.create_index()

pandas/tests/indexes/test_range.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -331,25 +331,31 @@ def test_is_monotonic(self):
331331
assert self.index.is_monotonic
332332
assert self.index.is_monotonic_increasing
333333
assert not self.index.is_monotonic_decreasing
334+
assert self.index.is_strictly_monotonic_increasing
335+
assert not self.index.is_strictly_monotonic_decreasing
334336

335337
index = RangeIndex(4, 0, -1)
336338
assert not index.is_monotonic
339+
assert not index.is_strictly_monotonic_increasing
337340
assert index.is_monotonic_decreasing
341+
assert index.is_strictly_monotonic_decreasing
338342

339343
index = RangeIndex(1, 2)
340344
assert index.is_monotonic
341345
assert index.is_monotonic_increasing
342346
assert index.is_monotonic_decreasing
347+
assert index.is_strictly_monotonic_increasing
348+
assert index.is_strictly_monotonic_decreasing
343349

344350
index = RangeIndex(2, 1)
345351
assert index.is_monotonic
346-
assert index.is_monotonic_increasing
347-
assert index.is_monotonic_decreasing
352+
assert index.is_strictly_monotonic_increasing
353+
assert index.is_strictly_monotonic_decreasing
348354

349355
index = RangeIndex(1, 1)
350356
assert index.is_monotonic
351-
assert index.is_monotonic_increasing
352-
assert index.is_monotonic_decreasing
357+
assert index.is_strictly_monotonic_increasing
358+
assert index.is_strictly_monotonic_decreasing
353359

354360
def test_equals_range(self):
355361
equiv_pairs = [(RangeIndex(0, 9, 2), RangeIndex(0, 10, 2)),

0 commit comments

Comments
 (0)