Skip to content

Commit e8e6e89

Browse files
jschendeljreback
authored andcommitted
BUG: Fix IntervalIndex.get_loc/get_indexer for IntervalIndex of length one (pandas-dev#20946)
1 parent c94a68c commit e8e6e89

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

doc/source/api.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,8 @@ IntervalIndex Components
16321632
IntervalIndex.length
16331633
IntervalIndex.values
16341634
IntervalIndex.is_non_overlapping_monotonic
1635+
IntervalIndex.get_loc
1636+
IntervalIndex.get_indexer
16351637

16361638

16371639
.. _api.multiindex:

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ Indexing
12481248
- Bug in ``Series.is_unique`` where extraneous output in stderr is shown if Series contains objects with ``__ne__`` defined (:issue:`20661`)
12491249
- Bug in ``.loc`` assignment with a single-element list-like incorrectly assigns as a list (:issue:`19474`)
12501250
- Bug in partial string indexing on a ``Series/DataFrame`` with a monotonic decreasing ``DatetimeIndex`` (:issue:`19362`)
1251+
- Bug in :meth:`IntervalIndex.get_loc` and :meth:`IntervalIndex.get_indexer` when used with an :class:`IntervalIndex` containing a single interval (:issue:`17284`, :issue:`20921`)
12511252

12521253
MultiIndex
12531254
^^^^^^^^^^

pandas/core/indexes/interval.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -159,20 +159,22 @@ class IntervalIndex(IntervalMixin, Index):
159159
160160
Attributes
161161
----------
162-
left
163-
right
164162
closed
165-
mid
163+
is_non_overlapping_monotonic
164+
left
166165
length
166+
mid
167+
right
167168
values
168-
is_non_overlapping_monotonic
169169
170170
Methods
171171
-------
172+
contains
172173
from_arrays
173-
from_tuples
174174
from_breaks
175-
contains
175+
from_tuples
176+
get_indexer
177+
get_loc
176178
177179
Examples
178180
---------
@@ -938,8 +940,11 @@ def _searchsorted_monotonic(self, label, side, exclude_label=False):
938940
if isinstance(label, IntervalMixin):
939941
raise NotImplementedError
940942

943+
# GH 20921: "not is_monotonic_increasing" for the second condition
944+
# instead of "is_monotonic_decreasing" to account for single element
945+
# indexes being both increasing and decreasing
941946
if ((side == 'left' and self.left.is_monotonic_increasing) or
942-
(side == 'right' and self.left.is_monotonic_decreasing)):
947+
(side == 'right' and not self.left.is_monotonic_increasing)):
943948
sub_idx = self.right
944949
if self.open_right or exclude_label:
945950
label = _get_next_label(label)

pandas/tests/indexes/interval/test_interval.py

+18
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,14 @@ def test_get_loc_interval(self):
497497
pytest.raises(KeyError, self.index.get_loc,
498498
Interval(-1, 0, 'left'))
499499

500+
# Make consistent with test_interval_new.py (see #16316, #16386)
501+
@pytest.mark.parametrize('item', [3, Interval(1, 4)])
502+
def test_get_loc_length_one(self, item, closed):
503+
# GH 20921
504+
index = IntervalIndex.from_tuples([(0, 5)], closed=closed)
505+
result = index.get_loc(item)
506+
assert result == 0
507+
500508
# To be removed, replaced by test_interval_new.py (see #16316, #16386)
501509
def test_get_indexer(self):
502510
actual = self.index.get_indexer([-1, 0, 0.5, 1, 1.5, 2, 3])
@@ -544,6 +552,16 @@ def test_get_indexer_subintervals(self):
544552
expected = np.array([0, 0, 0], dtype='intp')
545553
tm.assert_numpy_array_equal(actual, expected)
546554

555+
# Make consistent with test_interval_new.py (see #16316, #16386)
556+
@pytest.mark.parametrize('item', [
557+
[3], np.arange(1, 5), [Interval(1, 4)], interval_range(1, 4)])
558+
def test_get_indexer_length_one(self, item, closed):
559+
# GH 17284
560+
index = IntervalIndex.from_tuples([(0, 5)], closed=closed)
561+
result = index.get_indexer(item)
562+
expected = np.array([0] * len(item), dtype='intp')
563+
tm.assert_numpy_array_equal(result, expected)
564+
547565
# To be removed, replaced by test_interval_new.py (see #16316, #16386)
548566
def test_contains(self):
549567
# Only endpoints are valid.

0 commit comments

Comments
 (0)