# -*- coding: utf-8 -*- import numpy as np import pytest import pandas as pd from pandas import Index, IntervalIndex, MultiIndex from pandas.api.types import is_scalar def test_is_monotonic_increasing(): i = MultiIndex.from_product([np.arange(10), np.arange(10)], names=['one', 'two']) assert i.is_monotonic is True assert i._is_strictly_monotonic_increasing is True assert Index(i.values).is_monotonic is True assert i._is_strictly_monotonic_increasing is True i = MultiIndex.from_product([np.arange(10, 0, -1), np.arange(10)], names=['one', 'two']) assert i.is_monotonic is False assert i._is_strictly_monotonic_increasing is False assert Index(i.values).is_monotonic is False assert Index(i.values)._is_strictly_monotonic_increasing is False i = MultiIndex.from_product([np.arange(10), np.arange(10, 0, -1)], names=['one', 'two']) assert i.is_monotonic is False assert i._is_strictly_monotonic_increasing is False assert Index(i.values).is_monotonic is False assert Index(i.values)._is_strictly_monotonic_increasing is False i = MultiIndex.from_product([[1.0, np.nan, 2.0], ['a', 'b', 'c']]) assert i.is_monotonic is False assert i._is_strictly_monotonic_increasing is False assert Index(i.values).is_monotonic is False assert Index(i.values)._is_strictly_monotonic_increasing is False # string ordering i = MultiIndex(levels=[['foo', 'bar', 'baz', 'qux'], ['one', 'two', 'three']], codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]], names=['first', 'second']) assert i.is_monotonic is False assert Index(i.values).is_monotonic is False assert i._is_strictly_monotonic_increasing is False assert Index(i.values)._is_strictly_monotonic_increasing is False i = MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['mom', 'next', 'zenith']], codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]], names=['first', 'second']) assert i.is_monotonic is True assert Index(i.values).is_monotonic is True assert i._is_strictly_monotonic_increasing is True assert Index(i.values)._is_strictly_monotonic_increasing is True # mixed levels, hits the TypeError i = MultiIndex( levels=[[1, 2, 3, 4], ['gb00b03mlx29', 'lu0197800237', 'nl0000289783', 'nl0000289965', 'nl0000301109']], codes=[[0, 1, 1, 2, 2, 2, 3], [4, 2, 0, 0, 1, 3, -1]], names=['household_id', 'asset_id']) assert i.is_monotonic is False assert i._is_strictly_monotonic_increasing is False # empty i = MultiIndex.from_arrays([[], []]) assert i.is_monotonic is True assert Index(i.values).is_monotonic is True assert i._is_strictly_monotonic_increasing is True assert Index(i.values)._is_strictly_monotonic_increasing is True def test_is_monotonic_decreasing(): i = MultiIndex.from_product([np.arange(9, -1, -1), np.arange(9, -1, -1)], names=['one', 'two']) assert i.is_monotonic_decreasing is True assert i._is_strictly_monotonic_decreasing is True assert Index(i.values).is_monotonic_decreasing is True assert i._is_strictly_monotonic_decreasing is True i = MultiIndex.from_product([np.arange(10), np.arange(10, 0, -1)], names=['one', 'two']) assert i.is_monotonic_decreasing is False assert i._is_strictly_monotonic_decreasing is False assert Index(i.values).is_monotonic_decreasing is False assert Index(i.values)._is_strictly_monotonic_decreasing is False i = MultiIndex.from_product([np.arange(10, 0, -1), np.arange(10)], names=['one', 'two']) assert i.is_monotonic_decreasing is False assert i._is_strictly_monotonic_decreasing is False assert Index(i.values).is_monotonic_decreasing is False assert Index(i.values)._is_strictly_monotonic_decreasing is False i = MultiIndex.from_product([[2.0, np.nan, 1.0], ['c', 'b', 'a']]) assert i.is_monotonic_decreasing is False assert i._is_strictly_monotonic_decreasing is False assert Index(i.values).is_monotonic_decreasing is False assert Index(i.values)._is_strictly_monotonic_decreasing is False # string ordering i = MultiIndex(levels=[['qux', 'foo', 'baz', 'bar'], ['three', 'two', 'one']], codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]], names=['first', 'second']) assert i.is_monotonic_decreasing is False assert Index(i.values).is_monotonic_decreasing is False assert i._is_strictly_monotonic_decreasing is False assert Index(i.values)._is_strictly_monotonic_decreasing is False i = MultiIndex(levels=[['qux', 'foo', 'baz', 'bar'], ['zenith', 'next', 'mom']], codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]], names=['first', 'second']) assert i.is_monotonic_decreasing is True assert Index(i.values).is_monotonic_decreasing is True assert i._is_strictly_monotonic_decreasing is True assert Index(i.values)._is_strictly_monotonic_decreasing is True # mixed levels, hits the TypeError i = MultiIndex( levels=[[4, 3, 2, 1], ['nl0000301109', 'nl0000289965', 'nl0000289783', 'lu0197800237', 'gb00b03mlx29']], codes=[[0, 1, 1, 2, 2, 2, 3], [4, 2, 0, 0, 1, 3, -1]], names=['household_id', 'asset_id']) assert i.is_monotonic_decreasing is False assert i._is_strictly_monotonic_decreasing is False # empty i = MultiIndex.from_arrays([[], []]) assert i.is_monotonic_decreasing is True assert Index(i.values).is_monotonic_decreasing is True assert i._is_strictly_monotonic_decreasing is True assert Index(i.values)._is_strictly_monotonic_decreasing is True def test_is_strictly_monotonic_increasing(): idx = pd.MultiIndex(levels=[['bar', 'baz'], ['mom', 'next']], codes=[[0, 0, 1, 1], [0, 0, 0, 1]]) assert idx.is_monotonic_increasing is True assert idx._is_strictly_monotonic_increasing is False def test_is_strictly_monotonic_decreasing(): idx = pd.MultiIndex(levels=[['baz', 'bar'], ['next', 'mom']], codes=[[0, 0, 1, 1], [0, 0, 0, 1]]) assert idx.is_monotonic_decreasing is True assert idx._is_strictly_monotonic_decreasing is False def test_searchsorted_monotonic(indices): # GH17271 # not implemented for tuple searches in MultiIndex # or Intervals searches in IntervalIndex if isinstance(indices, (MultiIndex, IntervalIndex)): return # nothing to test if the index is empty if indices.empty: return value = indices[0] # determine the expected results (handle dupes for 'right') expected_left, expected_right = 0, (indices == value).argmin() if expected_right == 0: # all values are the same, expected_right should be length expected_right = len(indices) # test _searchsorted_monotonic in all cases # test searchsorted only for increasing if indices.is_monotonic_increasing: ssm_left = indices._searchsorted_monotonic(value, side='left') assert is_scalar(ssm_left) assert expected_left == ssm_left ssm_right = indices._searchsorted_monotonic(value, side='right') assert is_scalar(ssm_right) assert expected_right == ssm_right ss_left = indices.searchsorted(value, side='left') assert is_scalar(ss_left) assert expected_left == ss_left ss_right = indices.searchsorted(value, side='right') assert is_scalar(ss_right) assert expected_right == ss_right elif indices.is_monotonic_decreasing: ssm_left = indices._searchsorted_monotonic(value, side='left') assert is_scalar(ssm_left) assert expected_left == ssm_left ssm_right = indices._searchsorted_monotonic(value, side='right') assert is_scalar(ssm_right) assert expected_right == ssm_right else: # non-monotonic should raise. with pytest.raises(ValueError): indices._searchsorted_monotonic(value, side='left')