From ba96852782692e639364ffbfc537a7291d3a183b Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 09:57:17 +0900 Subject: [PATCH 01/12] warn the default reduction dimension of groupby --- xarray/__init__.py | 2 ++ xarray/core/common.py | 41 +++++++++++++++++++--------------- xarray/core/dataarray.py | 5 +++-- xarray/core/dataset.py | 9 +++++--- xarray/core/groupby.py | 16 ++++++++++++- xarray/core/variable.py | 6 +++-- xarray/tests/test_dataarray.py | 32 ++++++++++++++++++++------ 7 files changed, 78 insertions(+), 33 deletions(-) diff --git a/xarray/__init__.py b/xarray/__init__.py index 7cc7811b783..b0e377b2291 100644 --- a/xarray/__init__.py +++ b/xarray/__init__.py @@ -33,3 +33,5 @@ from . import tutorial from . import ufuncs from . import testing + +from .core.common import ALL_DIMS diff --git a/xarray/core/common.py b/xarray/core/common.py index 3f934fcc769..76b63589be0 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -6,22 +6,27 @@ import numpy as np import pandas as pd -from . import duck_array_ops, dtypes, formatting, ops +from . import duck_array_ops, dtypes, formatting, ops, utils from .arithmetic import SupportsArithmetic from .pycompat import OrderedDict, basestring, dask_array_type, suppress from .utils import Frozen, SortedKeysDict +# Use as a sentinel value to indicate a all dimensions, which +ALL_DIMS = utils.ReprObject('') +DEFAULT_DIMS = utils.ReprObject('') + + class ImplementsArrayReduce(object): @classmethod def _reduce_method(cls, func, include_skipna, numeric_only): if include_skipna: - def wrapped_func(self, dim=None, axis=None, skipna=None, + def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, skipna=None, keep_attrs=False, **kwargs): return self.reduce(func, dim, axis, keep_attrs=keep_attrs, skipna=skipna, allow_lazy=True, **kwargs) else: - def wrapped_func(self, dim=None, axis=None, keep_attrs=False, + def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, **kwargs): return self.reduce(func, dim, axis, keep_attrs=keep_attrs, allow_lazy=True, **kwargs) @@ -47,13 +52,13 @@ class ImplementsDatasetReduce(object): @classmethod def _reduce_method(cls, func, include_skipna, numeric_only): if include_skipna: - def wrapped_func(self, dim=None, keep_attrs=False, skipna=None, + def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, skipna=None, **kwargs): return self.reduce(func, dim, keep_attrs, skipna=skipna, numeric_only=numeric_only, allow_lazy=True, **kwargs) else: - def wrapped_func(self, dim=None, keep_attrs=False, **kwargs): + def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, **kwargs): return self.reduce(func, dim, keep_attrs, numeric_only=numeric_only, allow_lazy=True, **kwargs) @@ -308,12 +313,12 @@ def assign_coords(self, **kwargs): assigned : same type as caller A new object with the new coordinates in addition to the existing data. - + Examples -------- - + Convert longitude coordinates from 0-359 to -180-179: - + >>> da = xr.DataArray(np.random.rand(4), ... coords=[np.array([358, 359, 0, 1])], ... dims='lon') @@ -445,11 +450,11 @@ def groupby(self, group, squeeze=True): grouped : GroupBy A `GroupBy` object patterned after `pandas.GroupBy` that can be iterated over in the form of `(unique_value, grouped_array)` pairs. - + Examples -------- Calculate daily anomalies for daily data: - + >>> da = xr.DataArray(np.linspace(0, 1826, num=1827), ... coords=[pd.date_range('1/1/2000', '31/12/2004', ... freq='D')], @@ -465,7 +470,7 @@ def groupby(self, group, squeeze=True): Coordinates: * time (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 ... dayofyear (time) int64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... - + See Also -------- core.groupby.DataArrayGroupBy @@ -589,7 +594,7 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, closed=None, label=None, base=0, keep_attrs=False, **indexer): """Returns a Resample object for performing resampling operations. - Handles both downsampling and upsampling. If any intervals contain no + Handles both downsampling and upsampling. If any intervals contain no values from the original object, they will be given the value ``NaN``. Parameters @@ -616,11 +621,11 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, ------- resampled : same type as caller This object resampled. - + Examples -------- Downsample monthly time-series data to seasonal data: - + >>> da = xr.DataArray(np.linspace(0, 11, num=12), ... coords=[pd.date_range('15/12/1999', ... periods=12, freq=pd.DateOffset(months=1))], @@ -637,13 +642,13 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, * time (time) datetime64[ns] 1999-12-01 2000-03-01 2000-06-01 2000-09-01 Upsample monthly time-series data to daily data: - + >>> da.resample(time='1D').interpolate('linear') array([ 0. , 0.032258, 0.064516, ..., 10.935484, 10.967742, 11. ]) Coordinates: * time (time) datetime64[ns] 1999-12-15 1999-12-16 1999-12-17 ... - + References ---------- @@ -957,8 +962,8 @@ def contains_cftime_datetimes(var): sample = sample.item() return isinstance(sample, cftime_datetime) else: - return False - + return False + def _contains_datetime_like_objects(var): """Check if a variable contains datetime like objects (either diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index f215bc47df8..24cb1fbdaec 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -10,7 +10,7 @@ from ..plot.plot import _PlotMethods from .accessors import DatetimeAccessor from .alignment import align, reindex_like_indexers -from .common import AbstractArray, DataWithCoords +from .common import AbstractArray, DataWithCoords, ALL_DIMS, DEFAULT_DIMS from .coordinates import ( DataArrayCoordinates, Indexes, LevelCoordinatesSource, assert_coordinate_consistent, remap_label_indexers) @@ -1460,7 +1460,8 @@ def combine_first(self, other): """ return ops.fillna(self, other, join="outer") - def reduce(self, func, dim=None, axis=None, keep_attrs=False, **kwargs): + def reduce(self, func, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, + **kwargs): """Reduce this array by applying `func` along some dimension(s). Parameters diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 4b52178ad0e..554e7e77673 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -18,7 +18,8 @@ from .. import conventions from .alignment import align from .common import ( - DataWithCoords, ImplementsDatasetReduce, _contains_datetime_like_objects) + ALL_DIMS, DEFAULT_DIMS, DataWithCoords, ImplementsDatasetReduce, + _contains_datetime_like_objects) from .coordinates import ( DatasetCoordinates, Indexes, LevelCoordinatesSource, assert_coordinate_consistent, remap_label_indexers) @@ -2722,8 +2723,8 @@ def combine_first(self, other): out = ops.fillna(self, other, join="outer", dataset_join="outer") return out - def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, - allow_lazy=False, **kwargs): + def reduce(self, func, dim=DEFAULT_DIMS, keep_attrs=False, + numeric_only=False, allow_lazy=False, **kwargs): """Reduce this dataset by applying `func` along some dimension(s). Parameters @@ -2750,6 +2751,8 @@ def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, Dataset with this object's DataArrays replaced with new DataArrays of summarized data and the indicated dimension(s) removed. """ + if dim == DEFAULT_DIMS or dim == ALL_DIMS: + dim = None if isinstance(dim, basestring): dims = set([dim]) elif dim is None: diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 7068f8e6cae..1a03ea6539c 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, division, print_function import functools +import warnings import numpy as np import pandas as pd @@ -8,7 +9,8 @@ from . import dtypes, duck_array_ops, nputils, ops from .arithmetic import SupportsArithmetic from .combine import concat -from .common import ImplementsArrayReduce, ImplementsDatasetReduce +from .common import ( + ImplementsArrayReduce, ImplementsDatasetReduce, ALL_DIMS, DEFAULT_DIMS) from .pycompat import integer_types, range, zip from .utils import hashable, maybe_wrap_array, peek_at, safe_cast_to_index from .variable import IndexVariable, Variable, as_variable @@ -567,6 +569,18 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, Array with summarized data and the indicated dimension(s) removed. """ + if dim == DEFAULT_DIMS: + dim = ALL_DIMS + # TODO change this to dim = self._group_dim after + # the deprecation process + if self._obj.ndim > 1: + warnings.warn("Default reduction dimension will be changed to " + "the grouped dimension. To silence warning, set " + "dim=xarray.ALL_DIMS or dim=None explicitly.", + FutureWarning, stacklevel=2) + elif dim is None: + dim = self._group_dim + def reduce_array(ar): return ar.reduce(func, dim, axis, keep_attrs=keep_attrs, **kwargs) return self.apply(reduce_array, shortcut=shortcut) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index d9772407b82..280ba740809 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -1228,8 +1228,8 @@ def fillna(self, value): def where(self, cond, other=dtypes.NA): return ops.where_method(self, cond, other) - def reduce(self, func, dim=None, axis=None, keep_attrs=False, - allow_lazy=False, **kwargs): + def reduce(self, func, dim=common.DEFAULT_DIMS, axis=None, + keep_attrs=False, allow_lazy=False, **kwargs): """Reduce this array by applying `func` along some dimension(s). Parameters @@ -1258,6 +1258,8 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, Array with summarized data and the indicated dimension(s) removed. """ + if dim == common.DEFAULT_DIMS or dim == common.ALL_DIMS: + dim = None if dim is not None and axis is not None: raise ValueError("cannot supply both 'axis' and 'dim' arguments") diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 2950e97cc75..df58cb8226a 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -14,7 +14,7 @@ DataArray, Dataset, IndexVariable, Variable, align, broadcast, set_options) from xarray.convert import from_cdms2 from xarray.coding.times import CFDatetimeCoder, _import_cftime -from xarray.core.common import full_like +from xarray.core.common import full_like, ALL_DIMS from xarray.core.pycompat import OrderedDict, iteritems from xarray.tests import ( ReturnItem, TestCase, assert_allclose, assert_array_equal, assert_equal, @@ -1983,15 +1983,15 @@ def test_groupby_sum(self): self.x[:, 10:].sum(), self.x[:, 9:10].sum()]).T), 'abc': Variable(['abc'], np.array(['a', 'b', 'c']))})['foo'] - assert_allclose(expected_sum_all, grouped.reduce(np.sum)) - assert_allclose(expected_sum_all, grouped.sum()) + assert_allclose(expected_sum_all, grouped.reduce(np.sum, dim=ALL_DIMS)) + assert_allclose(expected_sum_all, grouped.sum(ALL_DIMS)) expected = DataArray([array['y'].values[idx].sum() for idx in [slice(9), slice(10, None), slice(9, 10)]], [['a', 'b', 'c']], ['abc']) actual = array['y'].groupby('abc').apply(np.sum) assert_allclose(expected, actual) - actual = array['y'].groupby('abc').sum() + actual = array['y'].groupby('abc').sum(ALL_DIMS) assert_allclose(expected, actual) expected_sum_axis1 = Dataset( @@ -2002,6 +2002,24 @@ def test_groupby_sum(self): assert_allclose(expected_sum_axis1, grouped.reduce(np.sum, 'y')) assert_allclose(expected_sum_axis1, grouped.sum('y')) + def test_groupby_warning(self): + array = self.make_groupby_example_array() + grouped = array.groupby('abc') + with pytest.warns(FutureWarning): + grouped.sum() + + def test_groupby_sum_default(self): + array = self.make_groupby_example_array() + grouped = array.groupby('abc') + + expected_sum_all = Dataset( + {'foo': Variable(['x', 'abc'], + np.array([self.x[:, :9].sum(axis=-1), + self.x[:, 10:].sum(axis=-1), + self.x[:, 9:10].sum(axis=-1)]).T), + 'abc': Variable(['abc'], np.array(['a', 'b', 'c']))})['foo'] + assert_allclose(expected_sum_all, grouped.sum(dim=None)) + def test_groupby_count(self): array = DataArray( [0, 0, np.nan, np.nan, 0, 0], @@ -2082,9 +2100,9 @@ def test_groupby_math(self): assert_identical(expected, actual) grouped = array.groupby('abc') - expected_agg = (grouped.mean() - np.arange(3)).rename(None) + expected_agg = (grouped.mean(ALL_DIMS) - np.arange(3)).rename(None) actual = grouped - DataArray(range(3), [('abc', ['a', 'b', 'c'])]) - actual_agg = actual.groupby('abc').mean() + actual_agg = actual.groupby('abc').mean(ALL_DIMS) assert_allclose(expected_agg, actual_agg) with raises_regex(TypeError, 'only support binary ops'): @@ -2158,7 +2176,7 @@ def test_groupby_multidim(self): ('lon', DataArray([5, 28, 23], coords=[('lon', [30., 40., 50.])])), ('lat', DataArray([16, 40], coords=[('lat', [10., 20.])]))]: - actual_sum = array.groupby(dim).sum() + actual_sum = array.groupby(dim).sum(ALL_DIMS) assert_identical(expected_sum, actual_sum) def test_groupby_multidim_apply(self): From fca04258f85e5187fdbf2d7f8f8fa4cd54e44e56 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 10:12:44 +0900 Subject: [PATCH 02/12] Only use DEFAULT_DIMS in groupby/resample --- xarray/core/common.py | 41 ++++++++++++++++++---------------------- xarray/core/dataarray.py | 4 ++-- xarray/core/dataset.py | 6 +++--- xarray/core/groupby.py | 29 ++++++++++++++++++++++------ xarray/core/variable.py | 6 +++--- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/xarray/core/common.py b/xarray/core/common.py index 76b63589be0..3f934fcc769 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -6,27 +6,22 @@ import numpy as np import pandas as pd -from . import duck_array_ops, dtypes, formatting, ops, utils +from . import duck_array_ops, dtypes, formatting, ops from .arithmetic import SupportsArithmetic from .pycompat import OrderedDict, basestring, dask_array_type, suppress from .utils import Frozen, SortedKeysDict -# Use as a sentinel value to indicate a all dimensions, which -ALL_DIMS = utils.ReprObject('') -DEFAULT_DIMS = utils.ReprObject('') - - class ImplementsArrayReduce(object): @classmethod def _reduce_method(cls, func, include_skipna, numeric_only): if include_skipna: - def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, skipna=None, + def wrapped_func(self, dim=None, axis=None, skipna=None, keep_attrs=False, **kwargs): return self.reduce(func, dim, axis, keep_attrs=keep_attrs, skipna=skipna, allow_lazy=True, **kwargs) else: - def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, + def wrapped_func(self, dim=None, axis=None, keep_attrs=False, **kwargs): return self.reduce(func, dim, axis, keep_attrs=keep_attrs, allow_lazy=True, **kwargs) @@ -52,13 +47,13 @@ class ImplementsDatasetReduce(object): @classmethod def _reduce_method(cls, func, include_skipna, numeric_only): if include_skipna: - def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, skipna=None, + def wrapped_func(self, dim=None, keep_attrs=False, skipna=None, **kwargs): return self.reduce(func, dim, keep_attrs, skipna=skipna, numeric_only=numeric_only, allow_lazy=True, **kwargs) else: - def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, **kwargs): + def wrapped_func(self, dim=None, keep_attrs=False, **kwargs): return self.reduce(func, dim, keep_attrs, numeric_only=numeric_only, allow_lazy=True, **kwargs) @@ -313,12 +308,12 @@ def assign_coords(self, **kwargs): assigned : same type as caller A new object with the new coordinates in addition to the existing data. - + Examples -------- - + Convert longitude coordinates from 0-359 to -180-179: - + >>> da = xr.DataArray(np.random.rand(4), ... coords=[np.array([358, 359, 0, 1])], ... dims='lon') @@ -450,11 +445,11 @@ def groupby(self, group, squeeze=True): grouped : GroupBy A `GroupBy` object patterned after `pandas.GroupBy` that can be iterated over in the form of `(unique_value, grouped_array)` pairs. - + Examples -------- Calculate daily anomalies for daily data: - + >>> da = xr.DataArray(np.linspace(0, 1826, num=1827), ... coords=[pd.date_range('1/1/2000', '31/12/2004', ... freq='D')], @@ -470,7 +465,7 @@ def groupby(self, group, squeeze=True): Coordinates: * time (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 ... dayofyear (time) int64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... - + See Also -------- core.groupby.DataArrayGroupBy @@ -594,7 +589,7 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, closed=None, label=None, base=0, keep_attrs=False, **indexer): """Returns a Resample object for performing resampling operations. - Handles both downsampling and upsampling. If any intervals contain no + Handles both downsampling and upsampling. If any intervals contain no values from the original object, they will be given the value ``NaN``. Parameters @@ -621,11 +616,11 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, ------- resampled : same type as caller This object resampled. - + Examples -------- Downsample monthly time-series data to seasonal data: - + >>> da = xr.DataArray(np.linspace(0, 11, num=12), ... coords=[pd.date_range('15/12/1999', ... periods=12, freq=pd.DateOffset(months=1))], @@ -642,13 +637,13 @@ def resample(self, freq=None, dim=None, how=None, skipna=None, * time (time) datetime64[ns] 1999-12-01 2000-03-01 2000-06-01 2000-09-01 Upsample monthly time-series data to daily data: - + >>> da.resample(time='1D').interpolate('linear') array([ 0. , 0.032258, 0.064516, ..., 10.935484, 10.967742, 11. ]) Coordinates: * time (time) datetime64[ns] 1999-12-15 1999-12-16 1999-12-17 ... - + References ---------- @@ -962,8 +957,8 @@ def contains_cftime_datetimes(var): sample = sample.item() return isinstance(sample, cftime_datetime) else: - return False - + return False + def _contains_datetime_like_objects(var): """Check if a variable contains datetime like objects (either diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 24cb1fbdaec..66d76125fd2 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -10,7 +10,7 @@ from ..plot.plot import _PlotMethods from .accessors import DatetimeAccessor from .alignment import align, reindex_like_indexers -from .common import AbstractArray, DataWithCoords, ALL_DIMS, DEFAULT_DIMS +from .common import AbstractArray, DataWithCoords, ALL_DIMS from .coordinates import ( DataArrayCoordinates, Indexes, LevelCoordinatesSource, assert_coordinate_consistent, remap_label_indexers) @@ -1460,7 +1460,7 @@ def combine_first(self, other): """ return ops.fillna(self, other, join="outer") - def reduce(self, func, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, + def reduce(self, func, dim=None, axis=None, keep_attrs=False, **kwargs): """Reduce this array by applying `func` along some dimension(s). diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 554e7e77673..f94bd4d2083 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -18,7 +18,7 @@ from .. import conventions from .alignment import align from .common import ( - ALL_DIMS, DEFAULT_DIMS, DataWithCoords, ImplementsDatasetReduce, + ALL_DIMS, DataWithCoords, ImplementsDatasetReduce, _contains_datetime_like_objects) from .coordinates import ( DatasetCoordinates, Indexes, LevelCoordinatesSource, @@ -2723,7 +2723,7 @@ def combine_first(self, other): out = ops.fillna(self, other, join="outer", dataset_join="outer") return out - def reduce(self, func, dim=DEFAULT_DIMS, keep_attrs=False, + def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, allow_lazy=False, **kwargs): """Reduce this dataset by applying `func` along some dimension(s). @@ -2751,7 +2751,7 @@ def reduce(self, func, dim=DEFAULT_DIMS, keep_attrs=False, Dataset with this object's DataArrays replaced with new DataArrays of summarized data and the indicated dimension(s) removed. """ - if dim == DEFAULT_DIMS or dim == ALL_DIMS: + if dim == ALL_DIMS: dim = None if isinstance(dim, basestring): dims = set([dim]) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 1a03ea6539c..79dda0055b6 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -6,11 +6,10 @@ import numpy as np import pandas as pd -from . import dtypes, duck_array_ops, nputils, ops +from . import dtypes, duck_array_ops, nputils, ops, utils from .arithmetic import SupportsArithmetic from .combine import concat -from .common import ( - ImplementsArrayReduce, ImplementsDatasetReduce, ALL_DIMS, DEFAULT_DIMS) +from .common import ALL_DIMS, ImplementsArrayReduce, ImplementsDatasetReduce from .pycompat import integer_types, range, zip from .utils import hashable, maybe_wrap_array, peek_at, safe_cast_to_index from .variable import IndexVariable, Variable, as_variable @@ -569,22 +568,40 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, Array with summarized data and the indicated dimension(s) removed. """ - if dim == DEFAULT_DIMS: + if dim is DEFAULT_DIMS: dim = ALL_DIMS # TODO change this to dim = self._group_dim after # the deprecation process if self._obj.ndim > 1: warnings.warn("Default reduction dimension will be changed to " "the grouped dimension. To silence warning, set " - "dim=xarray.ALL_DIMS or dim=None explicitly.", + "dim=xarray.ALL_DIMS explicitly.", FutureWarning, stacklevel=2) - elif dim is None: + if dim is None: # TODO enable this after the deprecation dim = self._group_dim def reduce_array(ar): return ar.reduce(func, dim, axis, keep_attrs=keep_attrs, **kwargs) return self.apply(reduce_array, shortcut=shortcut) + # TODO remove the following class method and DEFAULT_DIMS after the + # deprecation cycle + @classmethod + def _reduce_method(cls, func, include_skipna, numeric_only): + if include_skipna: + def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, skipna=None, + keep_attrs=False, **kwargs): + return self.reduce(func, dim, axis, keep_attrs=keep_attrs, + skipna=skipna, allow_lazy=True, **kwargs) + else: + def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, + **kwargs): + return self.reduce(func, dim, axis, keep_attrs=keep_attrs, + allow_lazy=True, **kwargs) + return wrapped_func + + +DEFAULT_DIMS = utils.ReprObject('') ops.inject_reduce_methods(DataArrayGroupBy) ops.inject_binary_ops(DataArrayGroupBy) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 280ba740809..99297c7e00f 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -1228,8 +1228,8 @@ def fillna(self, value): def where(self, cond, other=dtypes.NA): return ops.where_method(self, cond, other) - def reduce(self, func, dim=common.DEFAULT_DIMS, axis=None, - keep_attrs=False, allow_lazy=False, **kwargs): + def reduce(self, func, dim=None, axis=None, keep_attrs=False, + allow_lazy=False, **kwargs): """Reduce this array by applying `func` along some dimension(s). Parameters @@ -1258,7 +1258,7 @@ def reduce(self, func, dim=common.DEFAULT_DIMS, axis=None, Array with summarized data and the indicated dimension(s) removed. """ - if dim == common.DEFAULT_DIMS or dim == common.ALL_DIMS: + if dim == common.ALL_DIMS: dim = None if dim is not None and axis is not None: raise ValueError("cannot supply both 'axis' and 'dim' arguments") From b5d94c0fc9b2ac475d8079b593941017b40cbcbe Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 10:18:33 +0900 Subject: [PATCH 03/12] Restore unintended line break --- xarray/core/common.py | 6 +++++- xarray/core/dataarray.py | 3 +-- xarray/core/dataset.py | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/xarray/core/common.py b/xarray/core/common.py index 3f934fcc769..cb1fb62b635 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -9,7 +9,11 @@ from . import duck_array_ops, dtypes, formatting, ops from .arithmetic import SupportsArithmetic from .pycompat import OrderedDict, basestring, dask_array_type, suppress -from .utils import Frozen, SortedKeysDict +from .utils import Frozen, SortedKeysDict, ReprObject + + +# Use as a sentinel value to indicate a all dimensions, which +ALL_DIMS = ReprObject('') class ImplementsArrayReduce(object): diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 66d76125fd2..48bb9ed605c 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -1460,8 +1460,7 @@ def combine_first(self, other): """ return ops.fillna(self, other, join="outer") - def reduce(self, func, dim=None, axis=None, keep_attrs=False, - **kwargs): + def reduce(self, func, dim=None, axis=None, keep_attrs=False, **kwargs): """Reduce this array by applying `func` along some dimension(s). Parameters diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index f94bd4d2083..903f3d3f2f1 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -2723,8 +2723,8 @@ def combine_first(self, other): out = ops.fillna(self, other, join="outer", dataset_join="outer") return out - def reduce(self, func, dim=None, keep_attrs=False, - numeric_only=False, allow_lazy=False, **kwargs): + def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, + allow_lazy=False, **kwargs): """Reduce this dataset by applying `func` along some dimension(s). Parameters From cd16cb71ed8aaa842459195d266c1e721edd4dd7 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 10:55:57 +0900 Subject: [PATCH 04/12] Lint --- xarray/core/dataarray.py | 2 +- xarray/core/groupby.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 48bb9ed605c..f215bc47df8 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -10,7 +10,7 @@ from ..plot.plot import _PlotMethods from .accessors import DatetimeAccessor from .alignment import align, reindex_like_indexers -from .common import AbstractArray, DataWithCoords, ALL_DIMS +from .common import AbstractArray, DataWithCoords from .coordinates import ( DataArrayCoordinates, Indexes, LevelCoordinatesSource, assert_coordinate_consistent, remap_label_indexers) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 79dda0055b6..3a2b4f0e675 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -594,8 +594,8 @@ def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, skipna=None, return self.reduce(func, dim, axis, keep_attrs=keep_attrs, skipna=skipna, allow_lazy=True, **kwargs) else: - def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, keep_attrs=False, - **kwargs): + def wrapped_func(self, dim=DEFAULT_DIMS, axis=None, + keep_attrs=False, **kwargs): return self.reduce(func, dim, axis, keep_attrs=keep_attrs, allow_lazy=True, **kwargs) return wrapped_func From 1df4463fc288c41079cb76b6ba8bc9b05429203b Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 11:00:38 +0900 Subject: [PATCH 05/12] Add whatsnew --- doc/whats-new.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 0c62cca6093..34d8921a762 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -30,6 +30,14 @@ What's New v0.10.9 (unreleased) -------------------- +Breaking changes +~~~~~~~~~~~~~~~~ + +- Reduction of :py:meth:`DataArray.groupby` and :py:meth:`DataArray.resample` + without dimension argument will change in the next release. + Now we warn a FutureWarning. + By `Keisuke Fujii `_. + Documentation ~~~~~~~~~~~~~ From 604d2968d4ea42c717e2648816307bd3dfecb87f Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 11:26:37 +0900 Subject: [PATCH 06/12] Support dataset.groupby --- xarray/core/groupby.py | 31 ++++++++++++++++++++++++++++++- xarray/core/resample.py | 7 +++---- xarray/tests/test_dataset.py | 23 +++++++++++++++-------- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 3a2b4f0e675..c7a54585b33 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -577,7 +577,7 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, "the grouped dimension. To silence warning, set " "dim=xarray.ALL_DIMS explicitly.", FutureWarning, stacklevel=2) - if dim is None: # TODO enable this after the deprecation + elif dim is None: dim = self._group_dim def reduce_array(ar): @@ -680,10 +680,39 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Array with summarized data and the indicated dimension(s) removed. """ + if dim is DEFAULT_DIMS: + dim = ALL_DIMS + # TODO change this to dim = self._group_dim after + # the deprecation process + warnings.warn("Default reduction dimension will be changed to " + "the grouped dimension. To silence warning, set " + "dim=xarray.ALL_DIMS explicitly.", + FutureWarning, stacklevel=2) + elif dim is None: + dim = self._group_dim + def reduce_dataset(ds): return ds.reduce(func, dim, keep_attrs, **kwargs) return self.apply(reduce_dataset) + # TODO remove the following class method and DEFAULT_DIMS after the + # deprecation cycle + @classmethod + def _reduce_method(cls, func, include_skipna, numeric_only): + if include_skipna: + def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, + skipna=None, **kwargs): + return self.reduce(func, dim, keep_attrs, skipna=skipna, + numeric_only=numeric_only, allow_lazy=True, + **kwargs) + else: + def wrapped_func(self, dim=DEFAULT_DIMS, keep_attrs=False, + **kwargs): + return self.reduce(func, dim, keep_attrs, + numeric_only=numeric_only, allow_lazy=True, + **kwargs) + return wrapped_func + def assign(self, **kwargs): """Assign data variables by group. diff --git a/xarray/core/resample.py b/xarray/core/resample.py index 4933a09b257..81b8a4f5e7d 100644 --- a/xarray/core/resample.py +++ b/xarray/core/resample.py @@ -277,9 +277,6 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): """Reduce the items in this group by applying `func` along the pre-defined resampling dimension. - Note that `dim` is by default here and ignored if passed by the user; - this ensures compatibility with the existing reduce interface. - Parameters ---------- func : function @@ -299,8 +296,10 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Array with summarized data and the indicated dimension(s) removed. """ + print(self._dim) + print(self._group_dim) return super(DatasetResample, self).reduce( - func, self._dim, keep_attrs, **kwargs) + func, None, keep_attrs, **kwargs) def _interpolate(self, kind='linear'): """Apply scipy.interpolate.interp1d along resampling dimension.""" diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 08d71d462d8..86975c0de2a 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -14,7 +14,7 @@ import xarray as xr from xarray import ( DataArray, Dataset, IndexVariable, MergeError, Variable, align, backends, - broadcast, open_dataset, set_options) + broadcast, open_dataset, set_options, ALL_DIMS) from xarray.core import indexing, utils from xarray.core.common import full_like from xarray.core.pycompat import ( @@ -2609,20 +2609,28 @@ def test_groupby_reduce(self): expected = data.mean('y') expected['yonly'] = expected['yonly'].variable.set_dims({'x': 3}) - actual = data.groupby('x').mean() + actual = data.groupby('x').mean(ALL_DIMS) assert_allclose(expected, actual) actual = data.groupby('x').mean('y') assert_allclose(expected, actual) letters = data['letters'] - expected = Dataset({'xy': data['xy'].groupby(letters).mean(), + expected = Dataset({'xy': data['xy'].groupby(letters).mean(ALL_DIMS), 'xonly': (data['xonly'].mean().variable .set_dims({'letters': 2})), 'yonly': data['yonly'].groupby(letters).mean()}) - actual = data.groupby('letters').mean() + actual = data.groupby('letters').mean(ALL_DIMS) assert_allclose(expected, actual) + def test_groupby_warn(self): + data = Dataset({'xy': (['x', 'y'], np.random.randn(3, 4)), + 'xonly': ('x', np.random.randn(3)), + 'yonly': ('y', np.random.randn(4)), + 'letters': ('y', ['a', 'a', 'b', 'b'])}) + with pytest.warns(FutureWarning): + data.groupby('x').mean() + def test_groupby_math(self): def reorder_dims(x): return x.transpose('dim1', 'dim2', 'dim3', 'time') @@ -2677,7 +2685,7 @@ def test_groupby_math_virtual(self): ds = Dataset({'x': ('t', [1, 2, 3])}, {'t': pd.date_range('20100101', periods=3)}) grouped = ds.groupby('t.day') - actual = grouped - grouped.mean() + actual = grouped - grouped.mean(ALL_DIMS) expected = Dataset({'x': ('t', [0, 0, 0])}, ds[['t', 't.day']]) assert_identical(actual, expected) @@ -2686,18 +2694,17 @@ def test_groupby_nan(self): # nan should be excluded from groupby ds = Dataset({'foo': ('x', [1, 2, 3, 4])}, {'bar': ('x', [1, 1, 2, np.nan])}) - actual = ds.groupby('bar').mean() + actual = ds.groupby('bar').mean(ALL_DIMS) expected = Dataset({'foo': ('bar', [1.5, 3]), 'bar': [1, 2]}) assert_identical(actual, expected) def test_groupby_order(self): # groupby should preserve variables order - ds = Dataset() for vn in ['a', 'b', 'c']: ds[vn] = DataArray(np.arange(10), dims=['t']) data_vars_ref = list(ds.data_vars.keys()) - ds = ds.groupby('t').mean() + ds = ds.groupby('t').mean(ALL_DIMS) data_vars = list(ds.data_vars.keys()) assert data_vars == data_vars_ref # coords are now at the end of the list, so the test below fails From f6182ea1d0dff306978483927c1fe25d9f94385c Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Tue, 14 Aug 2018 21:32:08 +0900 Subject: [PATCH 07/12] Add a version in the warning message. --- xarray/core/groupby.py | 20 +++++++++++--------- xarray/core/resample.py | 2 -- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index c7a54585b33..1bad32db651 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -573,10 +573,11 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, # TODO change this to dim = self._group_dim after # the deprecation process if self._obj.ndim > 1: - warnings.warn("Default reduction dimension will be changed to " - "the grouped dimension. To silence warning, set " - "dim=xarray.ALL_DIMS explicitly.", - FutureWarning, stacklevel=2) + warnings.warn( + "Default reduction dimension will be changed to the " + "grouped dimension after xarray 0.11. To silence this " + "warning, pass dim=xarray.ALL_DIMS explicitly.", + FutureWarning, stacklevel=2) elif dim is None: dim = self._group_dim @@ -683,11 +684,12 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): if dim is DEFAULT_DIMS: dim = ALL_DIMS # TODO change this to dim = self._group_dim after - # the deprecation process - warnings.warn("Default reduction dimension will be changed to " - "the grouped dimension. To silence warning, set " - "dim=xarray.ALL_DIMS explicitly.", - FutureWarning, stacklevel=2) + # the deprecation process. Do not forget to remove _reduce_method + warnings.warn( + "Default reduction dimension will be changed to the " + "grouped dimension after xarray 0.11. To silence this " + "warning, pass dim=xarray.ALL_DIMS explicitly.", + FutureWarning, stacklevel=2) elif dim is None: dim = self._group_dim diff --git a/xarray/core/resample.py b/xarray/core/resample.py index 81b8a4f5e7d..0d392d888e5 100644 --- a/xarray/core/resample.py +++ b/xarray/core/resample.py @@ -296,8 +296,6 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Array with summarized data and the indicated dimension(s) removed. """ - print(self._dim) - print(self._group_dim) return super(DatasetResample, self).reduce( func, None, keep_attrs, **kwargs) From f80bdf2302af7d32fb3739ee76d5395043d4d058 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Thu, 16 Aug 2018 14:49:45 +0900 Subject: [PATCH 08/12] is -> == --- xarray/core/groupby.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 1bad32db651..a332f34ce07 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -568,7 +568,7 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, Array with summarized data and the indicated dimension(s) removed. """ - if dim is DEFAULT_DIMS: + if dim == DEFAULT_DIMS: dim = ALL_DIMS # TODO change this to dim = self._group_dim after # the deprecation process @@ -681,7 +681,7 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Array with summarized data and the indicated dimension(s) removed. """ - if dim is DEFAULT_DIMS: + if dim == DEFAULT_DIMS: dim = ALL_DIMS # TODO change this to dim = self._group_dim after # the deprecation process. Do not forget to remove _reduce_method From daafe87deea747a0e99bf34cf529a1b62152a957 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Thu, 16 Aug 2018 15:59:01 +0900 Subject: [PATCH 09/12] Update tests --- xarray/tests/test_dask.py | 4 ++-- xarray/tests/test_dataarray.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/tests/test_dask.py b/xarray/tests/test_dask.py index f6c47cce8d8..644271aff3c 100644 --- a/xarray/tests/test_dask.py +++ b/xarray/tests/test_dask.py @@ -378,8 +378,8 @@ def test_groupby(self): u = self.eager_array v = self.lazy_array - expected = u.groupby('x').mean() - actual = v.groupby('x').mean() + expected = u.groupby('x').mean(xr.ALL_DIMS) + actual = v.groupby('x').mean(xr.ALL_DIMS) self.assertLazyAndAllClose(expected, actual) def test_groupby_first(self): diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index df58cb8226a..e212ccc4582 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -2004,7 +2004,7 @@ def test_groupby_sum(self): def test_groupby_warning(self): array = self.make_groupby_example_array() - grouped = array.groupby('abc') + grouped = array.groupby('y') with pytest.warns(FutureWarning): grouped.sum() From 917e04aa6469d14bc528f2654d33b1058c3a5df5 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Thu, 16 Aug 2018 16:30:31 +0900 Subject: [PATCH 10/12] Update docs for DatasetResample.reduce --- xarray/core/resample.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/resample.py b/xarray/core/resample.py index 0d392d888e5..94b6b0ac264 100644 --- a/xarray/core/resample.py +++ b/xarray/core/resample.py @@ -283,6 +283,8 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Function which can be called in the form `func(x, axis=axis, **kwargs)` to return the result of collapsing an np.ndarray over an integer valued axis. + dim : str or sequence of str, optional + Dimension(s) over which to apply `func`. keep_attrs : bool, optional If True, the datasets's attributes (`attrs`) will be copied from the original object to the new one. If False (default), the new @@ -297,7 +299,7 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): removed. """ return super(DatasetResample, self).reduce( - func, None, keep_attrs, **kwargs) + func, dim, keep_attrs, **kwargs) def _interpolate(self, kind='linear'): """Apply scipy.interpolate.interp1d along resampling dimension.""" From 2c1e1edb1fb2adfb4c19425e288abcbe44293054 Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Thu, 16 Aug 2018 17:15:47 +0900 Subject: [PATCH 11/12] Match dataset.resample behavior to the current one. --- xarray/core/resample.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xarray/core/resample.py b/xarray/core/resample.py index 94b6b0ac264..25c149c51af 100644 --- a/xarray/core/resample.py +++ b/xarray/core/resample.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, print_function from . import ops -from .groupby import DataArrayGroupBy, DatasetGroupBy +from .groupby import DataArrayGroupBy, DatasetGroupBy, DEFAULT_DIMS from .pycompat import OrderedDict, dask_array_type RESAMPLE_DIM = '__resample_dim__' @@ -298,6 +298,9 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): Array with summarized data and the indicated dimension(s) removed. """ + if dim == DEFAULT_DIMS: + dim = None + return super(DatasetResample, self).reduce( func, dim, keep_attrs, **kwargs) From e7b73628c46ad5a24bfc5daf1981947a26b87e4c Mon Sep 17 00:00:00 2001 From: fujiisoup Date: Sun, 23 Sep 2018 17:00:13 +0900 Subject: [PATCH 12/12] Update via comments. --- xarray/core/common.py | 2 +- xarray/core/dataset.py | 10 +++++----- xarray/core/groupby.py | 6 ++---- xarray/core/variable.py | 2 +- xarray/tests/test_dataarray.py | 6 +++++- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/xarray/core/common.py b/xarray/core/common.py index 39501b9dd2e..41e4fec2982 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -13,7 +13,7 @@ from .utils import either_dict_or_kwargs, Frozen, SortedKeysDict, ReprObject -# Use as a sentinel value to indicate a all dimensions, which +# Used as a sentinel value to indicate a all dimensions ALL_DIMS = ReprObject('') diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index c58548eee1e..69975285e75 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -744,7 +744,7 @@ def copy(self, deep=False, data=None): Shallow copy versus deep copy >>> da = xr.DataArray(np.random.randn(2, 3)) - >>> ds = xr.Dataset({'foo': da, 'bar': ('x', [-1, 2])}, + >>> ds = xr.Dataset({'foo': da, 'bar': ('x', [-1, 2])}, coords={'x': ['one', 'two']}) >>> ds.copy() @@ -776,7 +776,7 @@ def copy(self, deep=False, data=None): foo (dim_0, dim_1) float64 7.0 0.3897 -1.862 -0.6091 -1.051 -0.3003 bar (x) int64 -1 2 - Changing the data using the ``data`` argument maintains the + Changing the data using the ``data`` argument maintains the structure of the original object, but with the new data. Original object is unaffected. @@ -827,7 +827,7 @@ def copy(self, deep=False, data=None): # skip __init__ to avoid costly validation return self._construct_direct(variables, self._coord_names.copy(), self._dims.copy(), self._attrs_copy(), - encoding=self.encoding) + encoding=self.encoding) def _subset_with_all_valid_coords(self, variables, coord_names, attrs): needed_dims = set() @@ -2866,7 +2866,7 @@ def combine_first(self, other): out = ops.fillna(self, other, join="outer", dataset_join="outer") return out - def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, + def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, allow_lazy=False, **kwargs): """Reduce this dataset by applying `func` along some dimension(s). @@ -2894,7 +2894,7 @@ def reduce(self, func, dim=None, keep_attrs=False, numeric_only=False, Dataset with this object's DataArrays replaced with new DataArrays of summarized data and the indicated dimension(s) removed. """ - if dim == ALL_DIMS: + if dim is ALL_DIMS: dim = None if isinstance(dim, basestring): dims = set([dim]) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index a332f34ce07..3842c642047 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -575,11 +575,9 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, if self._obj.ndim > 1: warnings.warn( "Default reduction dimension will be changed to the " - "grouped dimension after xarray 0.11. To silence this " + "grouped dimension after xarray 0.12. To silence this " "warning, pass dim=xarray.ALL_DIMS explicitly.", FutureWarning, stacklevel=2) - elif dim is None: - dim = self._group_dim def reduce_array(ar): return ar.reduce(func, dim, axis, keep_attrs=keep_attrs, **kwargs) @@ -687,7 +685,7 @@ def reduce(self, func, dim=None, keep_attrs=False, **kwargs): # the deprecation process. Do not forget to remove _reduce_method warnings.warn( "Default reduction dimension will be changed to the " - "grouped dimension after xarray 0.11. To silence this " + "grouped dimension after xarray 0.12. To silence this " "warning, pass dim=xarray.ALL_DIMS explicitly.", FutureWarning, stacklevel=2) elif dim is None: diff --git a/xarray/core/variable.py b/xarray/core/variable.py index e58dcfcbeda..c003d52aab2 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -1333,7 +1333,7 @@ def reduce(self, func, dim=None, axis=None, keep_attrs=False, Array with summarized data and the indicated dimension(s) removed. """ - if dim == common.ALL_DIMS: + if dim is common.ALL_DIMS: dim = None if dim is not None and axis is not None: raise ValueError("cannot supply both 'axis' and 'dim' arguments") diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 9030fd857c9..f8b288f4ab0 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -2,6 +2,7 @@ import pickle from copy import deepcopy +from distutils.version import LooseVersion from textwrap import dedent import warnings @@ -2025,6 +2026,8 @@ def test_groupby_warning(self): with pytest.warns(FutureWarning): grouped.sum() + @pytest.mark.skipif(LooseVersion(xr.__version__) < LooseVersion('0.12'), + reason="not to forget the behavior change") def test_groupby_sum_default(self): array = self.make_groupby_example_array() grouped = array.groupby('abc') @@ -2035,7 +2038,8 @@ def test_groupby_sum_default(self): self.x[:, 10:].sum(axis=-1), self.x[:, 9:10].sum(axis=-1)]).T), 'abc': Variable(['abc'], np.array(['a', 'b', 'c']))})['foo'] - assert_allclose(expected_sum_all, grouped.sum(dim=None)) + + assert_allclose(expected_sum_all, grouped.sum()) def test_groupby_count(self): array = DataArray(