diff --git a/doc/whats-new.rst b/doc/whats-new.rst index effb199f18e..f0b629fb063 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -29,6 +29,9 @@ Bug Fixes - Fix a major performance regression in :py:meth:`Coordinates.to_index` (and consequently :py:meth:`Dataset.to_dataframe`) caused by converting the cached code ndarrays into Python lists (:issue:`11305`). +- Fix :py:meth:`DataArray.idxmax` and :py:meth:`DataArray.idxmin` for interval + coordinates by preserving pandas extension index adapters during label lookup + (:issue:`11300`). Documentation diff --git a/xarray/compat/array_api_compat.py b/xarray/compat/array_api_compat.py index e1e5d5c5bdc..52d8506652b 100644 --- a/xarray/compat/array_api_compat.py +++ b/xarray/compat/array_api_compat.py @@ -1,5 +1,6 @@ import numpy as np +from xarray.core.utils import is_allowed_extension_array from xarray.namedarray.pycompat import array_type @@ -78,5 +79,7 @@ def to_like_array(array, like): xp = get_array_namespace(like) if xp is not np: return xp.asarray(array) + if is_allowed_extension_array(array): + return np.asarray(array) # avoid casting things like pint quantities to numpy arrays return array diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 8eb52046a31..d4eaabafc70 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -5530,6 +5530,30 @@ def test_idxmax( result7 = ar0.idxmax(fill_value=-1j) assert_identical(result7, expected7) + @pytest.mark.parametrize( + ("func_name", "values"), + [ + pytest.param("idxmax", [False, True, True], id="idxmax"), + pytest.param("idxmin", [True, False, True], id="idxmin"), + ], + ) + def test_idxminmax_interval_coords( + self, + x: np.ndarray, + minindex: int | float, + maxindex: int | float, + nanindex: int | None, + func_name: Literal["idxmax", "idxmin"], + values: list[bool], + ) -> None: + interval_index = pd.IntervalIndex.from_breaks([0, 1, 2, 3]) + array = xr.DataArray(values, dims=["z"], coords={"z": interval_index}) + + result = getattr(array, func_name)() + + expected = xr.DataArray(pd.Interval(1, 2, closed="right"), name="z") + assert_identical(result, expected) + @pytest.mark.filterwarnings( "ignore:Behaviour of argmin/argmax with neither dim nor :FutureWarning" )