pydata / pydata/xarray

[API]: inconsistent `rename` for DataArray vs Dataset

Open
#6,238 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

API design bug
Dominant language
Python
Stars
4.2k
Forks
1.4k
Avg merge
2d 15h
Merged PRs (30d)
14

Description

What happened?

The DataArray.rename API is inconsistent with Dataset.rename and the documentation does not make that obvious.

Unlike Dataset.rename,

  • A DataArray cannot be renamed using a keyword argument, but fails saying "[name] is not a variable or dimension in this dataset" (example A below).
  • Passing the new name as a positional argument, but with other keyword arguments fails with the statement "the first argument to .rename must be a dictionary" (example B below).
  • As a consequence, renaming the array as well as its dimension(s)/coordinate(s) requires two separate function calls, i.e. da.rename("newname").rename("dim_0"="x").

Examples

Start with an array, da, and a dataset, ds

>>> da = xr.DataArray(
    np.zeros((2,3)), 
    name="alpha",
    coords={"x":range(2), "y":range(3)}
)
>>> da
<xarray.DataArray 'alpha' (x: 2, y: 3)>
array([[0., 0., 0.],
       [0., 0., 0.]])
Coordinates:
  * x        (x) int64 0 1
  * y        (y) int64 0 1 2

>>> ds = xr.Dataset({"alpha":da})
>>> ds
<xarray.Dataset>
Dimensions:  (x: 2, y: 3)
Coordinates:
  * x        (x) int64 0 1
  * y        (y) int64 0 1 2
Data variables:
    alpha    (x, y) float64 0.0 0.0 0.0 0.0 0.0 0.0

Dataset example
ds.rename renames everything at once using keyword arguments

>>> ds.rename(x="i", y="j", alpha="beta")
<xarray.Dataset>
Dimensions:  (i: 2, j: 3)
Coordinates:
  * i        (i) int64 0 1
  * j        (j) int64 0 1 2
Data variables:
    beta     (i, j) float64 0.0 0.0 0.0 0.0 0.0 0.0

Example A
da.rename does not recognize the array's current name as a keyword and returns a confusing error message.

>>> da.rename(alpha="beta")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-98-af366146dc6f> in <module>
----> 1 da.rename(alpha="beta", x="i")

xarray/core/dataarray.py in rename(self, new_name_or_name_dict, **names)
   1842             )
   1843             name_dict = either_dict_or_kwargs(new_name_or_name_dict, names, "rename")
-> 1844             dataset = self._to_temp_dataset().rename(name_dict)
   1845             return self._from_temp_dataset(dataset)
   1846         else:

xarray/core/dataset.py in rename(self, name_dict, **names)
   3390         for k in name_dict.keys():
   3391             if k not in self and k not in self.dims:
-> 3392                 raise ValueError(
   3393                     f"cannot rename {k!r} because it is not a "
   3394                     "variable or dimension in this dataset"

ValueError: cannot rename 'alpha' because it is not a variable or dimension in this dataset

Example B
da.rename will not change the name of the array as well as the dimension(s)/coordinate(s) names and emits an untrue error message, since the array cannot be renamed using a dict.

>>> da.rename("beta", x="i")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-99-f90b078d6bd5> in <module>
----> 1 da.rename("beta", x="i")

xarray/core/dataarray.py in rename(self, new_name_or_name_dict, **names)
   1841                 Mapping[Hashable, Hashable], new_name_or_name_dict
   1842             )
-> 1843             name_dict = either_dict_or_kwargs(new_name_or_name_dict, names, "rename")
   1844             dataset = self._to_temp_dataset().rename(name_dict)
   1845             return self._from_temp_dataset(dataset)

xarray/core/utils.py in either_dict_or_kwargs(pos_kwargs, kw_kwargs, func_name)
    284
    285     if not is_dict_like(pos_kwargs):
--> 286         raise ValueError(f"the first argument to .{func_name} must be a dictionary")
    287     if kw_kwargs:
    288         raise ValueError(

ValueError: the first argument to .rename must be a dictionary
What did you expect to happen?

No response

Minimal Complete Verifiable Example

No response

Relevant log output

No response

Anything else we need to know?

No response

Environment

INSTALLED VERSIONS

commit: None
python: 3.9.10 | packaged by conda-forge | (main, Feb 1 2022, 21:25:34)
[Clang 11.1.0 ]
python-bits: 64
OS: Darwin
OS-release: 21.1.0
machine: arm64
processor: arm
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: ('en_US', 'UTF-8')
libhdf5: 1.12.1
libnetcdf: 4.8.1

xarray: 0.21.1
pandas: 1.3.5
numpy: 1.22.2
scipy: 1.7.1
netCDF4: 1.5.7
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: 1.5.2
nc_time_axis: None
PseudoNetCDF: None
rasterio: None
cfgrib: None
iris: None
bottleneck: 1.3.2
dask: None
distributed: None
matplotlib: 3.5.0
cartopy: None
seaborn: None
numbagg: None
fsspec: None
cupy: None
pint: None
sparse: None
setuptools: 60.7.1
pip: 22.0.3
conda: None
pytest: None
IPython: 7.29.0
sphinx: None

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the rename implementations shown in xarray/core/dataarray.py and xarray/core/dataset.py, and reproduce Examples A and B in a local checkout. Clarify the intended DataArray API for combining array-name and dimension or coordinate renames; done means consistent behavior with Dataset.rename and coverage for both examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
40/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.