Skip to content

Commit 883379c

Browse files
Fix to _get_nearest_indexer for pydata/xarray#3751 (#32905)
1 parent 754caad commit 883379c

File tree

5 files changed

+27
-5
lines changed

5 files changed

+27
-5
lines changed

doc/source/whatsnew/v1.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ Indexing
336336
- Bug in :meth:`DataFrame.iloc.__setitem__` on a :class:`DataFrame` with duplicate columns incorrectly setting values for all matching columns (:issue:`15686`, :issue:`22036`)
337337
- Bug in :meth:`DataFrame.loc:` and :meth:`Series.loc` with a :class:`DatetimeIndex`, :class:`TimedeltaIndex`, or :class:`PeriodIndex` incorrectly allowing lookups of non-matching datetime-like dtypes (:issue:`32650`)
338338
- Bug in :meth:`Series.__getitem__` indexing with non-standard scalars, e.g. ``np.dtype`` (:issue:`32684`)
339+
- Fix to preserve the ability to index with the "nearest" method with xarray's CFTimeIndex, an :class:`Index` subclass (`pydata/xarray#3751 <https://github.com/pydata/xarray/issues/3751>`_, :issue:`32905`).
339340
- Bug in :class:`Index` constructor where an unhelpful error message was raised for ``numpy`` scalars (:issue:`33017`)
340341
- Bug in :meth:`DataFrame.lookup` incorrectly raising an ``AttributeError`` when ``frame.index`` or ``frame.columns`` is not unique; this will now raise a ``ValueError`` with a helpful error message (:issue:`33041`)
341342

environment.yml

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ dependencies:
101101
- s3fs # pandas.read_csv... when using 's3://...' path
102102
- sqlalchemy # pandas.read_sql, DataFrame.to_sql
103103
- xarray # DataFrame.to_xarray
104+
- cftime # Needed for downstream xarray.CFTimeIndex test
104105
- pyreadstat # pandas.read_spss
105106
- tabulate>=0.8.3 # DataFrame.to_markdown
106107
- pip:

pandas/core/indexes/base.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -3049,8 +3049,9 @@ def _get_nearest_indexer(self, target: "Index", limit, tolerance) -> np.ndarray:
30493049
left_indexer = self.get_indexer(target, "pad", limit=limit)
30503050
right_indexer = self.get_indexer(target, "backfill", limit=limit)
30513051

3052-
left_distances = np.abs(self[left_indexer] - target)
3053-
right_distances = np.abs(self[right_indexer] - target)
3052+
target_values = target._values
3053+
left_distances = np.abs(self._values[left_indexer] - target_values)
3054+
right_distances = np.abs(self._values[right_indexer] - target_values)
30543055

30553056
op = operator.lt if self.is_monotonic_increasing else operator.le
30563057
indexer = np.where(
@@ -3059,13 +3060,16 @@ def _get_nearest_indexer(self, target: "Index", limit, tolerance) -> np.ndarray:
30593060
right_indexer,
30603061
)
30613062
if tolerance is not None:
3062-
indexer = self._filter_indexer_tolerance(target, indexer, tolerance)
3063+
indexer = self._filter_indexer_tolerance(target_values, indexer, tolerance)
30633064
return indexer
30643065

30653066
def _filter_indexer_tolerance(
3066-
self, target: "Index", indexer: np.ndarray, tolerance
3067+
self,
3068+
target: Union["Index", np.ndarray, ExtensionArray],
3069+
indexer: np.ndarray,
3070+
tolerance,
30673071
) -> np.ndarray:
3068-
distance = abs(self.values[indexer] - target)
3072+
distance = abs(self._values[indexer] - target)
30693073
indexer = np.where(distance <= tolerance, indexer, -1)
30703074
return indexer
30713075

pandas/tests/test_downstream.py

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import numpy as np # noqa
99
import pytest
1010

11+
import pandas.util._test_decorators as td
12+
1113
from pandas import DataFrame
1214
import pandas._testing as tm
1315

@@ -47,6 +49,19 @@ def test_xarray(df):
4749
assert df.to_xarray() is not None
4850

4951

52+
@td.skip_if_no("cftime")
53+
@td.skip_if_no("xarray", "0.10.4")
54+
def test_xarray_cftimeindex_nearest():
55+
# https://github.com/pydata/xarray/issues/3751
56+
import cftime
57+
import xarray
58+
59+
times = xarray.cftime_range("0001", periods=2)
60+
result = times.get_loc(cftime.DatetimeGregorian(2000, 1, 1), method="nearest")
61+
expected = 1
62+
assert result == expected
63+
64+
5065
def test_oo_optimizable():
5166
# GH 21071
5267
subprocess.check_call([sys.executable, "-OO", "-c", "import pandas"])

requirements-dev.txt

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ tables>=3.4.2
6868
s3fs
6969
sqlalchemy
7070
xarray
71+
cftime
7172
pyreadstat
7273
tabulate>=0.8.3
7374
git+https://github.com/pandas-dev/pydata-sphinx-theme.git@master

0 commit comments

Comments
 (0)