Skip to content

Commit 45c0a11

Browse files
authored
Raise UserWarning when rename creates a new dimension coord (#6999)
* warn when rename creates a new dimension coord UseWarning: no index is created anymore. * update what's new
1 parent 87596de commit 45c0a11

File tree

5 files changed

+83
-14
lines changed

5 files changed

+83
-14
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ Bug fixes
6565
By `András Gunyhó <https://github.com/mgunyho>`_.
6666
- Avoid use of random numbers in `test_weighted.test_weighted_operations_nonequal_coords` (:issue:`6504`, :pull:`6961`).
6767
By `Luke Conibear <https://github.com/lukeconibear>`_.
68+
- Raise a ``UserWarning`` when renaming a coordinate or a dimension creates a
69+
non-indexed dimension coordinate, and suggest the user creating an index
70+
either with ``swap_dims`` or ``set_index`` (:issue:`6607`, :pull:`6999`). By
71+
`Benoît Bovy <https://github.com/benbovy>`_.
6872
- Use ``keep_attrs=True`` in grouping and resampling operations by default (:issue:`7012`).
6973
This means :py:attr:`Dataset.attrs` and :py:attr:`DataArray.attrs` are now preserved by default.
7074
By `Deepak Cherian <https://github.com/dcherian>`_.

xarray/core/dataarray.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,11 +2063,11 @@ def rename(
20632063
if utils.is_dict_like(new_name_or_name_dict) or new_name_or_name_dict is None:
20642064
# change dims/coords
20652065
name_dict = either_dict_or_kwargs(new_name_or_name_dict, names, "rename")
2066-
dataset = self._to_temp_dataset().rename(name_dict)
2066+
dataset = self._to_temp_dataset()._rename(name_dict)
20672067
return self._from_temp_dataset(dataset)
20682068
if utils.hashable(new_name_or_name_dict) and names:
20692069
# change name + dims/coords
2070-
dataset = self._to_temp_dataset().rename(names)
2070+
dataset = self._to_temp_dataset()._rename(names)
20712071
dataarray = self._from_temp_dataset(dataset)
20722072
return dataarray._replace(name=new_name_or_name_dict)
20732073
# only change name

xarray/core/dataset.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,6 +3560,48 @@ def _rename_all(
35603560

35613561
return variables, coord_names, dims, indexes
35623562

3563+
def _rename(
3564+
self: T_Dataset,
3565+
name_dict: Mapping[Any, Hashable] | None = None,
3566+
**names: Hashable,
3567+
) -> T_Dataset:
3568+
"""Also used internally by DataArray so that the warning (if any)
3569+
is raised at the right stack level.
3570+
"""
3571+
name_dict = either_dict_or_kwargs(name_dict, names, "rename")
3572+
for k in name_dict.keys():
3573+
if k not in self and k not in self.dims:
3574+
raise ValueError(
3575+
f"cannot rename {k!r} because it is not a "
3576+
"variable or dimension in this dataset"
3577+
)
3578+
3579+
create_dim_coord = False
3580+
new_k = name_dict[k]
3581+
3582+
if k in self.dims and new_k in self._coord_names:
3583+
coord_dims = self._variables[name_dict[k]].dims
3584+
if coord_dims == (k,):
3585+
create_dim_coord = True
3586+
elif k in self._coord_names and new_k in self.dims:
3587+
coord_dims = self._variables[k].dims
3588+
if coord_dims == (new_k,):
3589+
create_dim_coord = True
3590+
3591+
if create_dim_coord:
3592+
warnings.warn(
3593+
f"rename {k!r} to {name_dict[k]!r} does not create an index "
3594+
"anymore. Try using swap_dims instead or use set_index "
3595+
"after rename to create an indexed coordinate.",
3596+
UserWarning,
3597+
stacklevel=3,
3598+
)
3599+
3600+
variables, coord_names, dims, indexes = self._rename_all(
3601+
name_dict=name_dict, dims_dict=name_dict
3602+
)
3603+
return self._replace(variables, coord_names, dims=dims, indexes=indexes)
3604+
35633605
def rename(
35643606
self: T_Dataset,
35653607
name_dict: Mapping[Any, Hashable] | None = None,
@@ -3588,18 +3630,7 @@ def rename(
35883630
Dataset.rename_dims
35893631
DataArray.rename
35903632
"""
3591-
name_dict = either_dict_or_kwargs(name_dict, names, "rename")
3592-
for k in name_dict.keys():
3593-
if k not in self and k not in self.dims:
3594-
raise ValueError(
3595-
f"cannot rename {k!r} because it is not a "
3596-
"variable or dimension in this dataset"
3597-
)
3598-
3599-
variables, coord_names, dims, indexes = self._rename_all(
3600-
name_dict=name_dict, dims_dict=name_dict
3601-
)
3602-
return self._replace(variables, coord_names, dims=dims, indexes=indexes)
3633+
return self._rename(name_dict=name_dict, **names)
36033634

36043635
def rename_dims(
36053636
self: T_Dataset,

xarray/tests/test_dataarray.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,23 @@ def test_rename(self) -> None:
17421742
)
17431743
assert_identical(renamed_all, expected_all)
17441744

1745+
def test_rename_dimension_coord_warnings(self) -> None:
1746+
# create a dimension coordinate by renaming a dimension or coordinate
1747+
# should raise a warning (no index created)
1748+
da = DataArray([0, 0], coords={"x": ("y", [0, 1])}, dims="y")
1749+
1750+
with pytest.warns(
1751+
UserWarning, match="rename 'x' to 'y' does not create an index.*"
1752+
):
1753+
da.rename(x="y")
1754+
1755+
da = xr.DataArray([0, 0], coords={"y": ("x", [0, 1])}, dims="x")
1756+
1757+
with pytest.warns(
1758+
UserWarning, match="rename 'x' to 'y' does not create an index.*"
1759+
):
1760+
da.rename(x="y")
1761+
17451762
def test_init_value(self) -> None:
17461763
expected = DataArray(
17471764
np.full((3, 4), 3), dims=["x", "y"], coords=[range(3), range(4)]

xarray/tests/test_dataset.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2892,6 +2892,23 @@ def test_rename_dimension_coord(self) -> None:
28922892
actual_2 = original.rename_dims({"x": "x_new"})
28932893
assert "x" in actual_2.xindexes
28942894

2895+
def test_rename_dimension_coord_warnings(self) -> None:
2896+
# create a dimension coordinate by renaming a dimension or coordinate
2897+
# should raise a warning (no index created)
2898+
ds = Dataset(coords={"x": ("y", [0, 1])})
2899+
2900+
with pytest.warns(
2901+
UserWarning, match="rename 'x' to 'y' does not create an index.*"
2902+
):
2903+
ds.rename(x="y")
2904+
2905+
ds = Dataset(coords={"y": ("x", [0, 1])})
2906+
2907+
with pytest.warns(
2908+
UserWarning, match="rename 'x' to 'y' does not create an index.*"
2909+
):
2910+
ds.rename(x="y")
2911+
28952912
def test_rename_multiindex(self) -> None:
28962913
mindex = pd.MultiIndex.from_tuples([([1, 2]), ([3, 4])], names=["a", "b"])
28972914
original = Dataset({}, {"x": mindex})

0 commit comments

Comments
 (0)