Stream: xarray

Topic: Identical dim/coord with different name- how to rename?


view this post on Zulip Daniel Adriaansen (Feb 01 2023 at 21:35):

I have this situation:

>>> ds
<xarray.Dataset>
Dimensions:  (x0: 3, y0: 3, y1: 3)
Coordinates:
  * x0       (x0) int64 0 1 2
  * y0       (y0) int64 0 1 2
  * y1       (y1) int64 0 1 2
Data variables:
    da1      (x0, y0) int64 20 30 40 50 60 70 80 90 100
    da2      (x0, y1) int64 20 30 40 50 60 70 80 90 100

I know that y0 and y1 are identical, and I do not want y1 to be a part of the dataset. I'd like to drop y1 as a dimension and coordinate, and reassign it to use y0 without losing variables. Does anyone have any tips on the combination of Xarray operators to accomplish this? Thanks!

view this post on Zulip Daniel Adriaansen (Feb 01 2023 at 22:05):

I can accomplish this in a for loop like this:

for v in ds.data_vars:
  if 'y1' in ds[v].coords:
    ds[v] = ds[v].swap_dims({'y1':'y0'})

But when I do:
ds.swap_dims({'y1':'y0'})

I get this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dadriaan/.conda/envs/icing/lib/python3.9/site-packages/xarray/core/dataset.py", line 3559, in swap_dims
    raise ValueError(
ValueError: replacement dimension 'y0' is not a 1D variable along the old dimension 'y1'

that I don't quite understand.

view this post on Zulip Deepak Cherian (Feb 02 2023 at 15:37):

Hmm that looks like a bug. How about a simple ds.rename_dims({"y1": "y0"})

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 15:43):

Deepak Cherian said:

Hmm that looks like a bug. How about a simple ds.rename_dims({"y1": "y0"})

ValueError: Cannot rename y1 to y0 because y0 already exists. Try using swap_dims instead.

:upside_down:

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 15:47):

Also, here is more code for testing:

import xarray as xr
da1 = xr.DataArray([[20,30,40],[50,60,70],[80,90,100]],dims=['x0','y0'],coords={'x0':[0,1,2],'y0':[0,1,2]})
da2 = xr.DataArray([[20,30,40],[50,60,70],[80,90,100]],dims=['x0','y1'],coords={'x0':[0,1,2],'y1':[0,1,2]})
ds = xr.Dataset(data_vars={'da1':da1,'da2':da2})
print(ds)
for v in ds.data_vars:
  if 'y1' in ds[v].coords:
    ds[v] = ds[v].swap_dims({'y1':'y0'})
print(ds)
#ds.swap_dims({'y1':'y0'})
#ds.rename_dims({"y1": "y0"})

I am using 2022.3.0. I will try it also with 2023.1.0 right now and see what I get.

view this post on Zulip Deepak Cherian (Feb 02 2023 at 15:47):

Oh yeah that might help. 2022.3.0 merged in some major under-the-hood changes, and many bugs have been fixed since then.

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 15:53):

Identical behavior:

>>> ds.swap_dims({'y1':'y0'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dadriaan/.conda/envs/xrbug/lib/python3.10/site-packages/xarray/core/dataset.py", line 3829, in swap_dims
    raise ValueError(
ValueError: replacement dimension 'y0' is not a 1D variable along the old dimension 'y1'
>>> print(xr.__version__)
2023.1.0
>>> ds.rename_dims({'y1':'y0'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dadriaan/.conda/envs/xrbug/lib/python3.10/site-packages/xarray/core/dataset.py", line 3707, in rename_dims
    raise ValueError(
ValueError: Cannot rename y1 to y0 because y0 already exists. Try using swap_dims instead.

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 17:41):

OK, the example code in the documentation returns the same error at this page:
https://docs.xarray.dev/en/stable/generated/xarray.Dataset.swap_dims.html

ds = xr.Dataset(
    data_vars={"a": ("x", [5, 7]), "b": ("x", [0.1, 2.4])},
    coords={"x": ["a", "b"], "y": ("x", [0, 1])},
)
ds.swap_dims({"x": "y"})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dadriaan/.conda/envs/xrbug/lib/python3.10/site-packages/xarray/core/dataset.py", line 3833, in swap_dims
    raise ValueError(
ValueError: replacement dimension 'y' is not a 1D variable along the old dimension 'x'

I will open an issue over on GitHub.

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 17:59):

Scratch that, the copy-paste from the docs caused that issue. If I reformat the creation of ds, it works. I will do some more testing.

view this post on Zulip Deepak Cherian (Feb 02 2023 at 18:02):

del ds["y1"]
ds.rename({"y1": "y0"})

this seems to work

view this post on Zulip Daniel Adriaansen (Feb 02 2023 at 18:36):

Interesting, that does work.

Also in dataset.py, it works if I comment out the section of code that causes it to fail:

            if v in self.variables and self.variables[v].dims != (k,):
                raise ValueError(
                    f"replacement dimension {v!r} is not a 1D "
                    f"variable along the old dimension {k!r}"
                )

I am struggling to understand what that code ^^^ is doing or what edge case it's designed to catch.

It also works if I choose a random name that doesn't exist in self.variables, because the second half of the and in the above code fails:

ds.swap_dims({"y1":"foo"})
<xarray.Dataset>
Dimensions:  (x0: 3, y0: 3, foo: 3)
Coordinates:
  * x0       (x0) int64 0 1 2
  * y0       (y0) int64 0 1 2
    y1       (foo) int64 0 1 2
Dimensions without coordinates: foo
Data variables:
    da1      (x0, y0) int64 20 30 40 50 60 70 80 90 100
    da2      (x0, foo) int64 20 30 40 50 60 70 80 90 100

Last updated: May 16 2025 at 17:14 UTC