diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 4c80a47209e..d755f6067a7 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -4334,9 +4334,9 @@ def rename_dims( f"cannot rename {k!r} because it is not found " f"in the dimensions of this dataset {tuple(self.dims)}" ) - if v in self.dims or v in self: + if v in self.dims: raise ValueError( - f"Cannot rename {k} to {v} because {v} already exists. " + f"Cannot rename dimension {k} to {v} because dimension {v} already exists. " "Try using swap_dims instead." ) @@ -4464,33 +4464,16 @@ def swap_dims( f"variable along the old dimension {current_name!r}" ) - result_dims = {dims_dict.get(dim, dim) for dim in self.dims} + result = self.rename_dims(dims_dict) + result = result.drop_indexes(dims_dict.keys(), errors="ignore") + for dim in dims_dict.values(): + if dim in result._variables: + if dim not in result._coord_names: + result = result.set_coords(dim) + if dim not in result._indexes: + result = result.set_xindex(dim) - coord_names = self._coord_names.copy() - coord_names.update({dim for dim in dims_dict.values() if dim in self.variables}) - - variables: dict[Hashable, Variable] = {} - indexes: dict[Hashable, Index] = {} - for current_name, current_variable in self.variables.items(): - dims = tuple(dims_dict.get(dim, dim) for dim in current_variable.dims) - var: Variable - if current_name in result_dims: - var = current_variable.to_index_variable() - var.dims = dims - if current_name in self._indexes: - indexes[current_name] = self._indexes[current_name] - variables[current_name] = var - else: - index, index_vars = create_default_index_implicit(var) - indexes.update({name: index for name in index_vars}) - variables.update(index_vars) - coord_names.update(index_vars) - else: - var = current_variable.to_base_variable() - var.dims = dims - variables[current_name] = var - - return self._replace_with_new_dims(variables, coord_names, indexes=indexes) + return result def expand_dims( self, diff --git a/xarray/testing/assertions.py b/xarray/testing/assertions.py index 6418eb79b8b..bb5b3576a00 100644 --- a/xarray/testing/assertions.py +++ b/xarray/testing/assertions.py @@ -273,7 +273,7 @@ def _assert_indexes_invariants_checks( if isinstance(index, PandasIndex): pd_index = index.index var = possible_coord_variables[k] - assert (index.dim,) == var.dims, (pd_index, var) + assert (index.dim,) == var.dims, (index, index.dim, var) if k == index.dim: # skip multi-index levels here (checked below) assert index.coord_dtype == var.dtype, (index.coord_dtype, var.dtype) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index e2a64964775..47fe6600064 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -3251,6 +3251,13 @@ def test_swap_dims(self) -> None: assert isinstance(actual.variables["x"], Variable) assert actual.xindexes["y"].equals(expected.xindexes["y"]) + def test_swap_dims_after_rename_vars(self) -> None: + # https://github.com/pydata/xarray/issues/8646 + ds = Dataset(coords={"y": [1, 2]}) + actual = ds.rename_vars(y="z").swap_dims(y="z") + expected = Dataset(coords={"z": [1, 2]}) + assert_identical(actual, expected) + def test_expand_dims_error(self) -> None: original = Dataset( {