|
11 | 11 | RangeIndex, MultiIndex, CategoricalIndex, DatetimeIndex,
|
12 | 12 | TimedeltaIndex, PeriodIndex, IntervalIndex,
|
13 | 13 | notna, isna)
|
| 14 | +from pandas.core.indexes.base import InvalidIndexError |
14 | 15 | from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
|
15 | 16 | from pandas.core.dtypes.common import needs_i8_conversion
|
16 | 17 | from pandas._libs.tslib import iNaT
|
@@ -138,9 +139,14 @@ def test_get_indexer_consistency(self):
|
138 | 139 | if isinstance(index, IntervalIndex):
|
139 | 140 | continue
|
140 | 141 |
|
141 |
| - indexer = index.get_indexer(index[0:2]) |
142 |
| - assert isinstance(indexer, np.ndarray) |
143 |
| - assert indexer.dtype == np.intp |
| 142 | + if index.is_unique or isinstance(index, CategoricalIndex): |
| 143 | + indexer = index.get_indexer(index[0:2]) |
| 144 | + assert isinstance(indexer, np.ndarray) |
| 145 | + assert indexer.dtype == np.intp |
| 146 | + else: |
| 147 | + e = "Reindexing only valid with uniquely valued Index objects" |
| 148 | + with tm.assert_raises_regex(InvalidIndexError, e): |
| 149 | + indexer = index.get_indexer(index[0:2]) |
144 | 150 |
|
145 | 151 | indexer, _ = index.get_indexer_non_unique(index[0:2])
|
146 | 152 | assert isinstance(indexer, np.ndarray)
|
@@ -632,7 +638,8 @@ def test_difference_base(self):
|
632 | 638 | pass
|
633 | 639 | elif isinstance(idx, (DatetimeIndex, TimedeltaIndex)):
|
634 | 640 | assert result.__class__ == answer.__class__
|
635 |
| - tm.assert_numpy_array_equal(result.asi8, answer.asi8) |
| 641 | + tm.assert_numpy_array_equal(result.sort_values().asi8, |
| 642 | + answer.sort_values().asi8) |
636 | 643 | else:
|
637 | 644 | result = first.difference(case)
|
638 | 645 | assert tm.equalContents(result, answer)
|
@@ -954,3 +961,47 @@ def test_join_self_unique(self, how):
|
954 | 961 | if index.is_unique:
|
955 | 962 | joined = index.join(index, how=how)
|
956 | 963 | assert (index == joined).all()
|
| 964 | + |
| 965 | + def test_searchsorted_monotonic(self): |
| 966 | + # GH17271 |
| 967 | + for index in self.indices.values(): |
| 968 | + # not implemented for tuple searches in MultiIndex |
| 969 | + # or Intervals searches in IntervalIndex |
| 970 | + if isinstance(index, (MultiIndex, IntervalIndex)): |
| 971 | + continue |
| 972 | + |
| 973 | + # nothing to test if the index is empty |
| 974 | + if index.empty: |
| 975 | + continue |
| 976 | + value = index[0] |
| 977 | + |
| 978 | + # determine the expected results (handle dupes for 'right') |
| 979 | + expected_left, expected_right = 0, (index == value).argmin() |
| 980 | + if expected_right == 0: |
| 981 | + # all values are the same, expected_right should be length |
| 982 | + expected_right = len(index) |
| 983 | + |
| 984 | + # test _searchsorted_monotonic in all cases |
| 985 | + # test searchsorted only for increasing |
| 986 | + if index.is_monotonic_increasing: |
| 987 | + ssm_left = index._searchsorted_monotonic(value, side='left') |
| 988 | + assert expected_left == ssm_left |
| 989 | + |
| 990 | + ssm_right = index._searchsorted_monotonic(value, side='right') |
| 991 | + assert expected_right == ssm_right |
| 992 | + |
| 993 | + ss_left = index.searchsorted(value, side='left') |
| 994 | + assert expected_left == ss_left |
| 995 | + |
| 996 | + ss_right = index.searchsorted(value, side='right') |
| 997 | + assert expected_right == ss_right |
| 998 | + elif index.is_monotonic_decreasing: |
| 999 | + ssm_left = index._searchsorted_monotonic(value, side='left') |
| 1000 | + assert expected_left == ssm_left |
| 1001 | + |
| 1002 | + ssm_right = index._searchsorted_monotonic(value, side='right') |
| 1003 | + assert expected_right == ssm_right |
| 1004 | + else: |
| 1005 | + # non-monotonic should raise. |
| 1006 | + with pytest.raises(ValueError): |
| 1007 | + index._searchsorted_monotonic(value, side='left') |
0 commit comments