Skip to content

Commit c8fe2d7

Browse files
authored
Add rename_like (#55)
Renames variables in object to match names of like-variables in ``other``. "Likeness" is determined by variables sharing similar attributes. If cf_xarray can identify a single "longitude" variable in both this object and ``other``, that variable will be renamed to match the "longitude" variable in ``other``. For now, this function only matches ``("latitude", "longitude", "vertical", "time")``
1 parent 4524510 commit c8fe2d7

File tree

6 files changed

+104
-4
lines changed

6 files changed

+104
-4
lines changed

cf_xarray/accessor.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ def _get_axis_coord_single(
158158
raise ValueError(
159159
f"Multiple results for {key!r} found: {results!r}. Is this valid CF? Please open an issue."
160160
)
161+
elif len(results) == 0:
162+
raise ValueError(f"No results found for {key!r}.")
161163
return results
162164

163165

@@ -276,6 +278,8 @@ def _get_measure(da: Union[xr.DataArray, xr.Dataset], key: str) -> List[Optional
276278
# We need this for groupby("T.month") and groupby("latitude") for example.
277279
_DEFAULT_KEY_MAPPERS: Mapping[str, Mapper] = {
278280
"dim": _get_axis_coord,
281+
"dims": _get_axis_coord, # is this necessary?
282+
"coords": _get_axis_coord, # interp
279283
"indexers": _get_axis_coord, # sel, isel
280284
"dims_or_levels": _get_axis_coord, # reset_index
281285
"coord": _get_axis_coord_single,
@@ -883,6 +887,56 @@ def add_bounds(self, dims: Union[Hashable, Iterable[Hashable]]):
883887

884888
return self._maybe_to_dataarray(obj)
885889

890+
def rename_like(
891+
self, other: Union[xr.DataArray, xr.Dataset]
892+
) -> Union[xr.DataArray, xr.Dataset]:
893+
"""
894+
Renames variables in object to match names of like-variables in ``other``.
895+
896+
"Likeness" is determined by variables sharing similar attributes. If
897+
cf_xarray can identify a single "longitude" variable in both this object and
898+
``other``, that variable will be renamed to match the "longitude" variable in
899+
``other``.
900+
901+
For now, this function only matches ``("latitude", "longitude", "vertical", "time")``
902+
903+
Parameters
904+
----------
905+
other: DataArray, Dataset
906+
Variables will be renamed to match variable names in this xarray object
907+
908+
Returns
909+
-------
910+
DataArray or Dataset with renamed variables
911+
"""
912+
ourkeys = self.get_valid_keys()
913+
theirkeys = other.cf.get_valid_keys()
914+
915+
good_keys = set(_COORD_NAMES) & ourkeys & theirkeys
916+
if not good_keys:
917+
raise ValueError(
918+
"No common coordinate variables between these two objects."
919+
)
920+
921+
renamer = {}
922+
for key in good_keys:
923+
ours = _get_axis_coord_single(self._obj, key)[0]
924+
theirs = _get_axis_coord_single(other, key)[0]
925+
renamer[ours] = theirs
926+
927+
newobj = self._obj.rename(renamer)
928+
929+
# rename variable names in the coordinates attribute
930+
# if present
931+
ds = self._maybe_to_dataset(newobj)
932+
for _, variable in ds.variables.items():
933+
coordinates = variable.attrs.get("coordinates", None)
934+
if coordinates:
935+
for k, v in renamer.items():
936+
coordinates = coordinates.replace(k, v)
937+
variable.attrs["coordinates"] = coordinates
938+
return self._maybe_to_dataarray(ds)
939+
886940

887941
@xr.register_dataset_accessor("cf")
888942
class CFDatasetAccessor(CFAccessor):

cf_xarray/tests/test_accessor.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,23 @@ def test_getitem_ancillary_variables():
9696
assert k not in popds.cf["UVEL"].coords
9797

9898

99+
def test_rename_like():
100+
original = popds.copy(deep=True)
101+
102+
with pytest.raises(ValueError):
103+
popds.cf.rename_like(airds)
104+
105+
renamed = popds.cf["TEMP"].cf.rename_like(airds)
106+
for k in ["TLONG", "TLAT"]:
107+
assert k not in renamed.coords
108+
assert k in original.coords
109+
assert original.TEMP.attrs["coordinates"] == "TLONG TLAT"
110+
111+
assert "lon" in renamed.coords
112+
assert "lat" in renamed.coords
113+
assert renamed.attrs["coordinates"] == "lon lat"
114+
115+
99116
@pytest.mark.parametrize("obj", objects)
100117
@pytest.mark.parametrize(
101118
"attr, xrkwargs, cfkwargs",

ci/doc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ dependencies:
1313
- ipython
1414
- ipykernel
1515
- pip:
16-
- cf_xarray
16+
- git+https://github.com/xarray-contrib/cf-xarray
1717
- sphinx-book-theme
1818
- git+https://github.com/keewis/sphinx-autosummary-accessors

doc/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ DataArray
1919
DataArray.cf.add_bounds
2020
DataArray.cf.describe
2121
DataArray.cf.get_valid_keys
22+
DataArray.cf.rename_like
2223

2324
Dataset
2425
-------
@@ -34,3 +35,4 @@ Dataset
3435
Dataset.cf.add_bounds
3536
Dataset.cf.describe
3637
Dataset.cf.get_valid_keys
38+
Dataset.cf.rename_like

doc/examples/introduction.ipynb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,30 @@
496496
"multiple.v1.cf.sizes"
497497
]
498498
},
499+
{
500+
"cell_type": "markdown",
501+
"metadata": {},
502+
"source": [
503+
"## Feature: Renaming coordinate variables\n",
504+
"\n",
505+
"`cf_xarray` lets you rewrite coordinate variables in one dataset to like\n",
506+
"variables in another dataset. This can only be done when a one-to-one mapping is\n",
507+
"possible\n",
508+
"\n",
509+
"In this example, `TLONG` and `TLAT` are renamed to `lon` and `lat` i.e. their\n",
510+
"counterparts in `ds`. Note the the `coordinates` attribute is appropriately\n",
511+
"changed.\n"
512+
]
513+
},
514+
{
515+
"cell_type": "code",
516+
"execution_count": null,
517+
"metadata": {},
518+
"outputs": [],
519+
"source": [
520+
"pop.cf[\"TEMP\"].cf.rename_like(ds)"
521+
]
522+
},
499523
{
500524
"cell_type": "markdown",
501525
"metadata": {},

doc/whats-new.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
What's New
22
----------
33

4-
v0.1.6
5-
======
4+
v0.1.6 (unreleased)
5+
===================
66

7-
- Added ```.cf.add_bounds`` to add guessed bounds for 1D coorindates. (:pr:`53`) `Deepak Cherian`_.
7+
- Added ``.cf.rename_like`` to rename matching variables. Only coordinate variables
8+
i.e. those that match the criteria for ``("latitude", "longitude", "vertical", "time")``
9+
are renamed for now. (:pr:`55`) `Deepak Cherian`_.
10+
- Added ``.cf.add_bounds`` to add guessed bounds for 1D coordinates. (:pr:`53`) `Deepak Cherian`_.
811

912
v0.1.5
1013
======

0 commit comments

Comments
 (0)