From 3478da73a5912f67c8d6c19496fb306e9f26d493 Mon Sep 17 00:00:00 2001 From: Benoit Bovy Date: Fri, 26 Jan 2024 11:38:18 +0100 Subject: [PATCH 1/3] fix serialize multi-index level coord after reset --- xarray/conventions.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/xarray/conventions.py b/xarray/conventions.py index 1d8e81e1bf2..61d0cc5e385 100644 --- a/xarray/conventions.py +++ b/xarray/conventions.py @@ -16,7 +16,7 @@ ) from xarray.core.pycompat import is_duck_dask_array from xarray.core.utils import emit_user_level_warning -from xarray.core.variable import Variable +from xarray.core.variable import IndexVariable, Variable CF_RELATED_DATA = ( "bounds", @@ -84,13 +84,17 @@ def _infer_dtype(array, name=None): def ensure_not_multiindex(var: Variable, name: T_Name = None) -> None: + # only the pandas multi-index dimension coordinate cannot be serialized (tuple values) if isinstance(var._data, indexing.PandasMultiIndexingAdapter): - raise NotImplementedError( - f"variable {name!r} is a MultiIndex, which cannot yet be " - "serialized. Instead, either use reset_index() " - "to convert MultiIndex levels into coordinate variables instead " - "or use https://cf-xarray.readthedocs.io/en/latest/coding.html." - ) + if name is None and isinstance(var, IndexVariable): + name = var.name + if var.dims == (name,): + raise NotImplementedError( + f"variable {name!r} is a MultiIndex, which cannot yet be " + "serialized. Instead, either use reset_index() " + "to convert MultiIndex levels into coordinate variables instead " + "or use https://cf-xarray.readthedocs.io/en/latest/coding.html." + ) def _copy_with_dtype(data, dtype: np.typing.DTypeLike): From 82ca94e9d0ed36922e9d301a1c24243e57b69239 Mon Sep 17 00:00:00 2001 From: Benoit Bovy Date: Fri, 26 Jan 2024 11:39:32 +0100 Subject: [PATCH 2/3] add regression test --- xarray/tests/test_backends.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xarray/tests/test_backends.py b/xarray/tests/test_backends.py index 85afbc1e147..03d2565d65e 100644 --- a/xarray/tests/test_backends.py +++ b/xarray/tests/test_backends.py @@ -1245,6 +1245,11 @@ def test_multiindex_not_implemented(self) -> None: with self.roundtrip(ds): pass + # regression GH8628 (can serialize reset multi-index level coordinates) + ds_reset = ds.reset_index("x") + with self.roundtrip(ds_reset) as actual: + assert_identical(actual, ds_reset) + class NetCDFBase(CFEncodedBase): """Tests for all netCDF3 and netCDF4 backends.""" From 1b8a636ab3bb56b71946aa58c1fc83978ae5902d Mon Sep 17 00:00:00 2001 From: Benoit Bovy Date: Fri, 26 Jan 2024 11:49:42 +0100 Subject: [PATCH 3/3] update what's new --- doc/whats-new.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index ac0015c14c5..97801d6e6b1 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -37,6 +37,9 @@ Deprecations Bug fixes ~~~~~~~~~ +- Fixed a regression that prevented multi-index level coordinates being + serialized after resetting or dropping the multi-index (:issue:`8628`, :pull:`8672`). + By `Benoit Bovy `_. Documentation ~~~~~~~~~~~~~