diff --git a/doc/whats-new.rst b/doc/whats-new.rst index b1d5b92da4d..05973bbd5f0 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -40,6 +40,7 @@ Enhancements :py:class:`pandas.DatetimeIndex`), which avoids unnecessary copies. By `Stephan Hoyer `_ + Bug fixes ~~~~~~~~~ @@ -150,7 +151,9 @@ Enhancements to returning (and is now deprecated). This was changed in order to facilitate using tutorial datasets with dask. By `Joe Hamman `_. - +- ``DataArray`` can now use ``xr.set_option(keep_attrs=True)`` and retain attributes in binary operations, + such as (``+, -, * ,/``). Default behaviour is unchanged (*Attributes will be dismissed*). By `Michael Blaschek `_ + Bug fixes ~~~~~~~~~ diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 0bff06e7546..7a921805258 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -1658,11 +1658,13 @@ def func(self, other): if isinstance(other, (xr.DataArray, xr.Dataset)): return NotImplemented self_data, other_data, dims = _broadcast_compat_data(self, other) + keep_attrs = _get_keep_attrs(default=False) + attrs = self._attrs if keep_attrs else None with np.errstate(all='ignore'): new_data = (f(self_data, other_data) if not reflexive else f(other_data, self_data)) - result = Variable(dims, new_data) + result = Variable(dims, new_data, attrs=attrs) return result return func diff --git a/xarray/tests/test_variable.py b/xarray/tests/test_variable.py index 0bd440781ac..84813f6c918 100644 --- a/xarray/tests/test_variable.py +++ b/xarray/tests/test_variable.py @@ -28,6 +28,8 @@ assert_allclose, assert_array_equal, assert_equal, assert_identical, raises_regex, requires_dask, source_ndarray) +from xarray import set_options + class VariableSubclassobjects(object): def test_properties(self): @@ -1545,6 +1547,18 @@ def test_reduce_keep_attrs(self): assert len(vm.attrs) == len(_attrs) assert vm.attrs == _attrs + def test_binary_ops_keep_attrs(self): + _attrs = {'units': 'test', 'long_name': 'testing'} + a = Variable(['x', 'y'], np.random.randn(3, 3), _attrs) + b = Variable(['x', 'y'], np.random.randn(3, 3), _attrs) + # Test dropped attrs + d = a - b # just one operation + assert d.attrs == OrderedDict() + # Test kept attrs + with set_options(keep_attrs=True): + d = a - b + assert d.attrs == _attrs + def test_count(self): expected = Variable([], 3) actual = Variable(['x'], [1, 2, 3, np.nan]).count()