Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to explicitly disable coordinates attribute #5514

Merged
merged 10 commits into from
Jul 1, 2021
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ New Features
By `Justus Magin <https://github.com/keewis>`_.
- Allow plotting categorical data (:pull:`5464`).
By `Jimmy Westling <https://github.com/illviljan>`_.
- Allow removal of the coordinate attribute ``coordinates`` on variables by setting ``.attrs['coordinates']= None``
(:issue:`5510`).
By `Elle Smith <https://github.com/ellesmith88>`_.

Breaking changes
~~~~~~~~~~~~~~~~
Expand Down
5 changes: 5 additions & 0 deletions xarray/conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,10 @@ def _encode_coordinates(variables, attributes, non_dim_coord_names):
f"'coordinates' found in both attrs and encoding for variable {name!r}."
)

# if coordinates set to None, don't write coordinates attribute
if "coordinates" in attrs and attrs.get("coordinates") is None:
andersy005 marked this conversation as resolved.
Show resolved Hide resolved
continue

# this will copy coordinates from encoding to attrs if "coordinates" in attrs
# after the next line, "coordinates" is never in encoding
# we get support for attrs["coordinates"] for free.
Expand All @@ -772,6 +776,7 @@ def _encode_coordinates(variables, attributes, non_dim_coord_names):
# conventions, only do it if necessary.
# Reference discussion:
# http://mailman.cgd.ucar.edu/pipermail/cf-metadata/2014/007571.html

ellesmith88 marked this conversation as resolved.
Show resolved Hide resolved
global_coordinates.difference_update(written_coords)
if global_coordinates:
attributes = dict(attributes)
Expand Down
25 changes: 25 additions & 0 deletions xarray/tests/test_conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,31 @@ def test_do_not_overwrite_user_coordinates(self):
with pytest.raises(ValueError, match=r"'coordinates' found in both attrs"):
conventions.encode_dataset_coordinates(orig)

def test_emit_coordinates_attribute(self):
orig = Dataset(
{
"foo": (("x", "y"), np.random.randn(2, 3)),
"x": [10, 20],
"bar": ("x", [1, 2]),
}
)
orig = orig.assign_coords(
{"t": np.array("2004-11-01T00:00:00", dtype=np.datetime64)}
)
orig = orig.assign({"a": 1})
orig = orig.assign({"b": 1})
ellesmith88 marked this conversation as resolved.
Show resolved Hide resolved

orig["a"].attrs["coordinates"] = None
enc, _ = conventions.encode_dataset_coordinates(orig)

# check coordiante attribute emitted for 'a'
assert enc["a"].attrs.get("coordinates") is None
assert enc["a"].encoding.get("coordinates") is None

# check coordinate attribute not emitted for 'b'
assert enc["b"].attrs.get("coordinates") == "t"
assert enc["b"].encoding.get("coordinates") is None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice tests.

Let's also test for when orig.a.encoding["coordinates"] = None


@requires_dask
def test_string_object_warning(self):
original = Variable(("x",), np.array(["foo", "bar"], dtype=object)).chunk()
Expand Down