Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ Bug Fixes
- Ensure the :py:class:`~xarray.groupers.SeasonResampler` preserves the datetime
unit of the underlying time index when resampling (:issue:`11048`,
:pull:`11049`). By `Spencer Clark <https://github.com/spencerkclark>`_.
- Partially support pandas 3 default string indexes by coercing ``pd.StringDtype``
to ``np.dtypes.StringDType`` in ``PandasIndexingAdapter`` (:issue:`11098`, :pull:`11102`).
By `Julia Signell <https://github.com/jsignell>`_.

Documentation
~~~~~~~~~~~~~
Expand Down
3 changes: 3 additions & 0 deletions xarray/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from numpy.typing import DTypeLike
from packaging.version import Version

from xarray.compat.npcompat import HAS_STRING_DTYPE
from xarray.core import duck_array_ops
from xarray.core.coordinate_transform import CoordinateTransform
from xarray.core.nputils import NumpyVIndexAdapter
Expand Down Expand Up @@ -1916,6 +1917,8 @@ def __init__(
self._dtype = get_valid_numpy_dtype(array)
elif is_allowed_extension_array_dtype(dtype):
self._dtype = cast(pd.api.extensions.ExtensionDtype, dtype)
elif HAS_STRING_DTYPE and isinstance(dtype, pd.StringDtype):
self._dtype = np.dtypes.StringDType(na_object=dtype.na_value)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alippai this is the only change to the code in this PR, so xarray isn't doing any coercion, just changing the dtype attribute.

else:
self._dtype = np.dtype(cast(DTypeLike, dtype))

Expand Down
2 changes: 1 addition & 1 deletion xarray/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def _importorskip(
has_flox, requires_flox = _importorskip("flox")
has_netcdf, requires_netcdf = _importorskip("netcdf")
has_pandas_ge_2_2, requires_pandas_ge_2_2 = _importorskip("pandas", "2.2")
has_pandas_3, requires_pandas_3 = _importorskip("pandas", "3.0.0.dev0")
has_pandas_3, requires_pandas_3 = _importorskip("pandas", "3.0.0")


# some special cases
Expand Down
10 changes: 9 additions & 1 deletion xarray/tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pandas as pd
import pytest

from xarray import DataArray, Dataset, Variable
from xarray import DataArray, Dataset, Variable, concat
from xarray.core import indexing, nputils
from xarray.core.indexes import PandasIndex, PandasMultiIndex
from xarray.core.types import T_Xarray
Expand All @@ -18,6 +18,7 @@
assert_identical,
raise_if_dask_computes,
requires_dask,
requires_pandas_3,
)
from xarray.tests.arrays import DuckArrayWrapper

Expand Down Expand Up @@ -1192,3 +1193,10 @@ def test_backend_indexing_non_numpy() -> None:
raw_indexing_method=array.__getitem__,
)
np.testing.assert_array_equal(indexed.array, np.array([1]))


@requires_pandas_3
def test_pandas_StringDtype_index_coerces_to_numpy() -> None:
da = DataArray([0, 1], coords={"x": ["x1", "x2"]})
actual = concat([da, da], dim=pd.Index(["y1", "y2"], name="y"))
assert isinstance(actual["y"].dtype, np.dtypes.StringDType)
Loading