diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 77d6296acac..d3cc3356102 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -79,6 +79,8 @@ Bug fixes By `Victor Negîrneac `_. - Don't allow passing ``axis`` to :py:meth:`Dataset.reduce` methods (:issue:`3510`, :pull:`4940`). By `Justus Magin `_. +- Convert to IndexVariable or Variable during renaming as appropriate. (:issue:`4107`, :issue:`4417`, :pull:`4108`) + By `Deepak Cherian `_. - Decode values as signed if attribute `_Unsigned = "false"` (:issue:`4954`) By `Tobias Kölling `_. diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 19b3eec5f07..086e496bf39 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -3006,7 +3006,7 @@ def _rename_dims(self, name_dict): def _rename_indexes(self, name_dict, dims_set): if self._indexes is None: - return None + return {} indexes = {} for k, v in self.indexes.items(): new_name = name_dict.get(k, k) @@ -3024,6 +3024,24 @@ def _rename_all(self, name_dict, dims_dict): variables, coord_names = self._rename_vars(name_dict, dims_dict) dims = self._rename_dims(dims_dict) indexes = self._rename_indexes(name_dict, dims.keys()) + + # Variable could be renamed to an existing dimension name + # in this case, convert to IndexVariable and set indexes + # GH4107 + for name in set(self.dims) & set(variables) - set(indexes): + variables[name] = variables[name].to_index_variable() + indexes[name] = variables[name].to_index() + coord_names.add(name) + + # rename_dims was called to rename an indexed dimension + # the new renamed dimension is unindexed + # remove the old variable from indexes and convert to a base variable + if indexes: + for name, newname in dims_dict.items(): + if name != newname and name in indexes: + variables[name] = variables[name].to_base_variable() + del indexes[name] + return variables, coord_names, dims, indexes def rename( diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 52df7603034..c525db63160 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -2673,6 +2673,22 @@ def test_rename_vars(self): with pytest.raises(ValueError): original.rename_vars(names_dict_bad) + def test_rename_to_dim_name(self): + # regression test for GH4107 + coord_1 = xr.DataArray([1, 2], dims=["coord_1"], attrs={"attrs": True}) + ds = xr.Dataset() + ds["a"] = xr.DataArray([1, 0], [coord_1]) + obj = ds.reset_index("coord_1").rename({"coord_1_": "coord_1"}) + assert_equal(ds, obj) + + newds = ( + ds.reset_index("coord_1") + .reset_coords("coord_1_") + .rename({"coord_1_": "coord_1"}) + ) + assert "coord_1" not in newds.data_vars + assert_equal(newds, obj) + def test_rename_multiindex(self): mindex = pd.MultiIndex.from_tuples( [([1, 2]), ([3, 4])], names=["level0", "level1"]