diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 694f2201d9f34..725b793cc9b7a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3900,9 +3900,10 @@ def _check_indexing_method( "tolerance not implemented yet for MultiIndex" ) - if isinstance(self.dtype, (IntervalDtype, CategoricalDtype)): + if isinstance(self.dtype, (CategoricalDtype)): # GH#37871 for now this is only for IntervalIndex and CategoricalIndex - if method is not None: + if method is not None: # and method not in ("bfill", "backfill") + # and not is_interval_dtype(self.dtype): raise NotImplementedError( f"method {method} not yet implemented for {type(self).__name__}" ) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 13c87a9d06b66..bba0af0545576 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -702,6 +702,12 @@ def _get_indexer( # we should always have self._should_partial_index(target) here target = self._maybe_convert_i8(target) indexer = self._engine.get_indexer(target.values) + + # if indexer is int: + if (indexer == [-1]).all() and method in ("bfill", "backfill"): + # GH#51503 + indexer = self._get_indexer_ffill(target, method) + else: # heterogeneous scalar index: defer elementwise to get_loc # we should always have self._should_partial_index(target) here @@ -709,6 +715,25 @@ def _get_indexer( return ensure_platform_int(indexer) + def _get_indexer_ffill(self, target, method): + # GH#51503 + if method in ("bfill", "backfill"): + temp = [] + _len_self = len(self) + for i in range(_len_self): + # not sure to call this method for every value + t = self._maybe_cast_listlike_indexer([self[i]]) + temp.append(self._maybe_convert_i8(t)) + + for i in range(_len_self): + # TODO: Comparing is not written professionally. Needs more review + if target[0] < temp[i].values[0].left: + return [i] + + return -1 + else: + return -1 + @Appender(_index_shared_docs["get_indexer_non_unique"] % _index_doc_kwargs) def get_indexer_non_unique( self, target: Index diff --git a/pandas/tests/indexes/interval/test_indexing.py b/pandas/tests/indexes/interval/test_indexing.py index e7db8076efa2b..840e2ed4aed85 100644 --- a/pandas/tests/indexes/interval/test_indexing.py +++ b/pandas/tests/indexes/interval/test_indexing.py @@ -424,6 +424,24 @@ def test_get_indexer_interval_index(self, box): expected = np.array([-1, -1, -1], dtype=np.intp) tm.assert_numpy_array_equal(actual, expected) + def test_get_indexer_with_backfill(self): + # GH#51503 + dt = Timestamp.now() + h = Timedelta("1h") + + # 3 simple interval ranges, with a big gap between 2nd and 3rd + intervals = IntervalIndex.from_arrays( + [dt, dt + h, dt + 10 * h], [dt + h, dt + 2 * h, dt + 11 * h], closed="left" + ) + + result = intervals.get_indexer([dt + 5 * h], method="bfill") + # result = intervals.get_indexer([dt + 5 * h]) + # result = intervals.get_indexer([dt + 10 * h], method="nearest") + + expected = np.array([2], dtype=np.intp) + + tm.assert_numpy_array_equal(result, expected) + class TestSliceLocs: def test_slice_locs_with_interval(self):