Skip to content

Commit

Permalink
concat keeps attrs from first variable. (#3637)
Browse files Browse the repository at this point in the history
* concat keep attrs from first variable.

Fixes #2060
Fixes #2575
  • Loading branch information
dcherian authored and TomNicholas committed Dec 24, 2019
1 parent 3cbc459 commit aaf3738
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 10 deletions.
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ Breaking changes

New Features
~~~~~~~~~~~~
- :py:func:`xarray.concat` now preserves attributes from the first Variable.
(:issue:`2575`, :issue:`2060`, :issue:`1614`)
By `Deepak Cherian <https://github.com/dcherian>`_.
- :py:meth:`Dataset.quantile`, :py:meth:`DataArray.quantile` and ``GroupBy.quantile``
now work with dask Variables.
By `Deepak Cherian <https://github.com/dcherian>`_.
Expand Down
6 changes: 4 additions & 2 deletions xarray/core/concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ def concat(
those of the first object with that dimension. Indexes for the same
dimension must have the same size in all objects.
indexers, mode, concat_over : deprecated
Returns
-------
concatenated : type of objs
Notes
-----
Each concatenated Variable preserves corresponding ``attrs`` from the first element of ``objs``.
See also
--------
merge
Expand Down
5 changes: 3 additions & 2 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -1625,8 +1625,9 @@ def concat(cls, variables, dim="concat_dim", positions=None, shortcut=False):
if not shortcut:
for var in variables:
if var.dims != first_var.dims:
raise ValueError("inconsistent dimensions")
utils.remove_incompatible_items(attrs, var.attrs)
raise ValueError(
f"Variable has dimensions {list(var.dims)} but first Variable has dimensions {list(first_var.dims)}"
)

return cls(dims, data, attrs, encoding)

Expand Down
13 changes: 13 additions & 0 deletions xarray/tests/test_concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,16 @@ def test_concat_join_kwarg(self):
for join in expected:
actual = concat([ds1, ds2], join=join, dim="x")
assert_equal(actual, expected[join].to_array())


@pytest.mark.parametrize("attr1", ({"a": {"meta": [10, 20, 30]}}, {"a": [1, 2, 3]}, {}))
@pytest.mark.parametrize("attr2", ({"a": [1, 2, 3]}, {}))
def test_concat_attrs_first_variable(attr1, attr2):

arrs = [
DataArray([[1], [2]], dims=["x", "y"], attrs=attr1),
DataArray([[3], [4]], dims=["x", "y"], attrs=attr2),
]

concat_attrs = concat(arrs, "y").attrs
assert concat_attrs == attr1
8 changes: 2 additions & 6 deletions xarray/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def test_concat(self):
assert_identical(
Variable(["b", "a"], np.array([x, y])), Variable.concat((v, w), "b")
)
with raises_regex(ValueError, "inconsistent dimensions"):
with raises_regex(ValueError, "Variable has dimensions"):
Variable.concat([v, Variable(["c"], y)], "b")
# test indexers
actual = Variable.concat(
Expand All @@ -451,16 +451,12 @@ def test_concat(self):
Variable.concat([v[:, 0], v[:, 1:]], "x")

def test_concat_attrs(self):
# different or conflicting attributes should be removed
# always keep attrs from first variable
v = self.cls("a", np.arange(5), {"foo": "bar"})
w = self.cls("a", np.ones(5))
expected = self.cls(
"a", np.concatenate([np.arange(5), np.ones(5)])
).to_base_variable()
assert_identical(expected, Variable.concat([v, w], "a"))
w.attrs["foo"] = 2
assert_identical(expected, Variable.concat([v, w], "a"))
w.attrs["foo"] = "bar"
expected.attrs["foo"] = "bar"
assert_identical(expected, Variable.concat([v, w], "a"))

Expand Down

0 comments on commit aaf3738

Please sign in to comment.