You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Convert pandas str indexes to numpy StringDType consistently #11785
Follow-up to #11322. With pandas 3, a default string index (StringDtype(na_value=nan)) only becomes a numpy StringDType coordinate when it's passed as the dim of concat. Everywhere else it becomes object:
The reason is that PandasIndexingAdapter only maps pd.StringDtype to np.dtypes.StringDType when the dtype is passed explicitly (#11102), and only the concat dim path in _calc_concat_dim_index does that. In all other cases PandasIndexingAdapter falls back to get_valid_numpy_dtype (xarray/core/utils.py), which returns object for any non-numpy dtype.
As discussed in #11322 (comment), the plan is to use StringDType everywhere, following #11098. Since the minimum supported numpy version is now 2.2, StringDType is always available, so no object fallback for older numpy versions is needed. That probably means:
Map pd.StringDtype to np.dtypes.StringDType(na_object=dtype.na_value) in get_valid_numpy_dtype (or wherever the default coord dtype is picked), so that PandasIndex and PandasIndexingAdapter don't need the dtype passed explicitly.
If StringDType becomes the default for pandas strings, the .str accessor needs some work too. I compared every accessor method on the same data as <U and as StringDType(). Without missing values, almost everything gives the same values, and string-returning methods keep StringDType. These are the gaps (xarray main, numpy 2.5.4):
importnumpyasnpimportxarrayasxrsdt=np.dtypes.StringDType()
da=xr.DataArray(np.array(["abc", "a_b"], dtype=sdt), dims="x")
u=xr.DataArray(["abc", "a_b"], dims="x")
da.str.extract(r"(.)(.)", dim="g")
# AttributeError: 'str' object has no attribute 'dtype'u.str.contains(da) # same for replace, cat, + with a StringDType argument# TypeError: cannot cast dtype StringDType() to <class 'numpy.dtypes.StrDType'>.nan_sdt=np.dtypes.StringDType(na_object=np.nan)
xr.DataArray(np.array(["a", np.nan], dtype=nan_sdt)).str.upper()
# AttributeError: 'float' object has no attribute 'upper'xr.DataArray(np.array(["a_b"], dtype=nan_sdt)).str.split(dim="p", sep="_").dtype# StringDType() (na_object is lost)
extract with dim: elements of a StringDType array are plain Python str, so val.dtype in _get_res_multi fails. Using dtype=object there would be enough, since the result is cast afterwards anyway.
Mixed <U/StringDType: _stringify casts arguments with astype(self._obj.dtype.kind), i.e. astype("U"), which numpy doesn't allow for StringDType.
na_object is lost: several methods cast their result with astype(self._obj.dtype.kind) ("T"), which gives the default StringDType() (e.g. cat/+, split, partition, extract).
Missing values: with na_object=np.nan (what pandas 3 str data maps to) or None, almost every method fails. Object arrays with NaN fail the same way, so the accessor never supported missing values, but with StringDType it becomes much more common.
test_accessor_str.py only covers np.str_ and np.bytes_.
Activity
headtr1ck commentedon Oct 22, 2026
If
StringDTypebecomes the default for pandas strings, the.straccessor needs some work too. I compared every accessor method on the same data as<Uand asStringDType(). Without missing values, almost everything gives the same values, and string-returning methods keepStringDType. These are the gaps (xarraymain, numpy 2.5.4):extractwithdim: elements of aStringDTypearray are plain Pythonstr, soval.dtypein_get_res_multifails. Usingdtype=objectthere would be enough, since the result is cast afterwards anyway.<U/StringDType:_stringifycasts arguments withastype(self._obj.dtype.kind), i.e.astype("U"), which numpy doesn't allow forStringDType.na_objectis lost: several methods cast their result withastype(self._obj.dtype.kind)("T"), which gives the defaultStringDType()(e.g.cat/+,split,partition,extract).na_object=np.nan(what pandas 3strdata maps to) orNone, almost every method fails. Object arrays withNaNfail the same way, so the accessor never supported missing values, but withStringDTypeit becomes much more common.test_accessor_str.pyonly coversnp.str_andnp.bytes_.FIX: Preserve pandas StringDtype on xarray coordinates
FIX: Preserve pandas StringDtype and missing markers for coordinates
FIX: Preserve pandas StringDtype across xarray coordinates and DataFr…
FIX: Preserve pandas StringDtype across coordinates and DataFrame export
FIX: preserve pandas StringDtype in coordinate and DataFrame round-trips
FIX: preserve pandas StringDtype coordinates and unsupported missing …
FIX: consistently preserve pandas StringDtype in xarray coordinates
TST: Align StringDType repr doctests and static typing with CI
FIX: consistently preserve pandas StringDtype in xarray coordinates
TST: Align StringDType repr doctests and static typing with CI