From 776bc5a6f75a7b98199aee22db4e940d7a497c8f Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 14:44:06 +0100 Subject: [PATCH 01/74] use cumsum from flox --- xarray/core/_aggregations.py | 43 +++++++++++++++--- xarray/core/groupby.py | 88 +++++++++++++++++++++++++++++------- 2 files changed, 108 insertions(+), 23 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index adc064840de..75e11d41e1c 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -6647,6 +6647,13 @@ def _flox_reduce( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -7904,13 +7911,35 @@ def cumsum( * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) tuple[Hashable, ...]: + parsed_dim: tuple[Hashable, ...] + if isinstance(dim, str): + parsed_dim = (dim,) + elif dim is None: + parsed_dim_list = list() + # preserve order + for dim_ in itertools.chain( + *(grouper.codes.dims for grouper in self.groupers) + ): + if dim_ not in parsed_dim_list: + parsed_dim_list.append(dim_) + parsed_dim = tuple(parsed_dim_list) + elif dim is ...: + parsed_dim = tuple(obj.dims) + else: + parsed_dim = tuple(dim) + + return parsed_dim + def _flox_reduce( self, dim: Dims, @@ -1088,22 +1108,7 @@ def _flox_reduce( # set explicitly to avoid unnecessarily accumulating count kwargs["min_count"] = 0 - parsed_dim: tuple[Hashable, ...] - if isinstance(dim, str): - parsed_dim = (dim,) - elif dim is None: - parsed_dim_list = list() - # preserve order - for dim_ in itertools.chain( - *(grouper.codes.dims for grouper in self.groupers) - ): - if dim_ not in parsed_dim_list: - parsed_dim_list.append(dim_) - parsed_dim = tuple(parsed_dim_list) - elif dim is ...: - parsed_dim = tuple(obj.dims) - else: - parsed_dim = tuple(dim) + parsed_dim = self._parse_dim(dim) # Do this so we raise the same error message whether flox is present or not. # Better to control it here than in flox. @@ -1202,6 +1207,57 @@ def _flox_reduce( return result + def _flox_scan( + self, + dim: Dims, + *, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + + from flox import groupby_scan + + # def groupby_scan( + # array: np.ndarray | DaskArray, + # *by: T_By, + # func: T_Scan, + # expected_groups: T_ExpectedGroupsOpt = None, + # axis: int | tuple[int] = -1, + # dtype: np.typing.DTypeLike = None, + # method: T_MethodOpt = None, + # engine: T_EngineOpt = None, + # ) -> np.ndarray | DaskArray: + + if keep_attrs is None: + keep_attrs = _get_keep_attrs(default=True) + + parsed_dim = self._parse_dim(dim) + obj = self._original_obj + codes = tuple(g.codes for g in self.groupers) + a = 2 + g = groupby_scan( + obj.data, + *codes, + func=kwargs["func"], + expected_groups=None, + axis=obj.get_axis_num(parsed_dim), + dtype=None, + method=None, + engine=None, + ) + + return obj.copy(data=g) + + # xarray_reduce( + # obj.drop_vars(non_numeric.keys()), + # *codes, + # dim=parsed_dim, + # expected_groups=expected_groups, + # isbin=False, + # keep_attrs=keep_attrs, + # **kwargs, + # ) + def fillna(self, value: Any) -> T_Xarray: """Fill missing values in this object by group. From ae276323902ca46ccb16c35b87d941c3ad57df0e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 13:44:51 +0000 Subject: [PATCH 02/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 4f80cdba3b7..1b6a726adff 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1214,7 +1214,6 @@ def _flox_scan( keep_attrs: bool | None = None, **kwargs: Any, ) -> DataArray: - from flox import groupby_scan # def groupby_scan( From a5f93265db48cee749212af73198bfe1d2f5f1b5 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 14:47:26 +0100 Subject: [PATCH 03/74] Update groupby.py --- xarray/core/groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 1b6a726adff..45b0e7906bf 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1042,7 +1042,7 @@ def _parse_dim(self, dim: Dims) -> tuple[Hashable, ...]: parsed_dim_list.append(dim_) parsed_dim = tuple(parsed_dim_list) elif dim is ...: - parsed_dim = tuple(obj.dims) + parsed_dim = tuple(self._original_obj.dims) else: parsed_dim = tuple(dim) From 50ccca4ad3b415ab9a0e749b6ae95da8b5c3d04f Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 14:48:52 +0100 Subject: [PATCH 04/74] Update groupby.py --- xarray/core/groupby.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 45b0e7906bf..9daff837dcf 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,9 +252,7 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d( - group: T_Group, obj: T_DataWithCoords -) -> tuple[ +def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, @@ -1233,7 +1231,7 @@ def _flox_scan( parsed_dim = self._parse_dim(dim) obj = self._original_obj codes = tuple(g.codes for g in self.groupers) - a = 2 + g = groupby_scan( obj.data, *codes, From f55531ef0ac4de3a523623f44366ed2eff470a1f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 13:49:56 +0000 Subject: [PATCH 05/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 9daff837dcf..806ca838ec3 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,7 +252,9 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ +def _ensure_1d( + group: T_Group, obj: T_DataWithCoords +) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, From 06ac3724cd709f73ea497746a2a0931b41205b8e Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:00:49 +0100 Subject: [PATCH 06/74] Update groupby.py --- xarray/core/groupby.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 9daff837dcf..c9aefcc1cde 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1209,41 +1209,40 @@ def _flox_scan( self, dim: Dims, *, + func: str, keep_attrs: bool | None = None, + skipna: bool | None = None **kwargs: Any, ) -> DataArray: from flox import groupby_scan - # def groupby_scan( - # array: np.ndarray | DaskArray, - # *by: T_By, - # func: T_Scan, - # expected_groups: T_ExpectedGroupsOpt = None, - # axis: int | tuple[int] = -1, - # dtype: np.typing.DTypeLike = None, - # method: T_MethodOpt = None, - # engine: T_EngineOpt = None, - # ) -> np.ndarray | DaskArray: + obj = self._original_obj + + if skipna or ( + skipna is None and isinstance(func, str) and obj.dtype.kind in "cfO" + ): + if "nan" not in func and func not in ["all", "any", "count"]: + func = f"nan{func}" if keep_attrs is None: keep_attrs = _get_keep_attrs(default=True) parsed_dim = self._parse_dim(dim) - obj = self._original_obj codes = tuple(g.codes for g in self.groupers) g = groupby_scan( obj.data, *codes, - func=kwargs["func"], + func=func, expected_groups=None, axis=obj.get_axis_num(parsed_dim), dtype=None, method=None, engine=None, ) + result = obj.copy(data=g) - return obj.copy(data=g) + return result # xarray_reduce( # obj.drop_vars(non_numeric.keys()), From dd475368ed5b5cb5d89f28ba418b4729bf88f66c Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:02:30 +0100 Subject: [PATCH 07/74] Update groupby.py --- xarray/core/groupby.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index cad7f210e6e..c38a1b592d7 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,9 +252,7 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d( - group: T_Group, obj: T_DataWithCoords -) -> tuple[ +def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, @@ -1213,7 +1211,7 @@ def _flox_scan( *, func: str, keep_attrs: bool | None = None, - skipna: bool | None = None + skipna: bool | None = None, **kwargs: Any, ) -> DataArray: from flox import groupby_scan From e867f12c880a156bbb740a2424dc21a1046476e6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 14:03:01 +0000 Subject: [PATCH 08/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index c38a1b592d7..3a8f5dfdb28 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,7 +252,9 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ +def _ensure_1d( + group: T_Group, obj: T_DataWithCoords +) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, From 88e0ebc31f1da827c094702fd0e337746cc75263 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:20:12 +0100 Subject: [PATCH 09/74] Update groupby.py --- xarray/core/groupby.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 3a8f5dfdb28..ec67ad4cb13 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,9 +252,7 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d( - group: T_Group, obj: T_DataWithCoords -) -> tuple[ +def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, @@ -1230,14 +1228,16 @@ def _flox_scan( keep_attrs = _get_keep_attrs(default=True) parsed_dim = self._parse_dim(dim) - codes = tuple(g.codes for g in self.groupers) + axis_ = obj.get_axis_num(parsed_dim) + axis = (axis_,) if isinstance(axis_, int) else axis_ + codes = tuple(g.codes for g in self.groupers) g = groupby_scan( obj.data, *codes, func=func, expected_groups=None, - axis=obj.get_axis_num(parsed_dim), + axis=axis, dtype=None, method=None, engine=None, From 181d4a38f51e411e86ffff32561d5bef9fc99ccf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 14:20:37 +0000 Subject: [PATCH 10/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index ec67ad4cb13..a4fb8a6359e 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -252,7 +252,9 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ +def _ensure_1d( + group: T_Group, obj: T_DataWithCoords +) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, From a82ec398c8bec3c17b07fadcc3ae407bc8f27168 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:44:38 +0100 Subject: [PATCH 11/74] use apply_ufunc for dataset and dataarray handling --- xarray/core/_aggregations.py | 8 ------ xarray/core/groupby.py | 53 ++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 75e11d41e1c..aa4bec25a11 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -7911,14 +7911,6 @@ def cumsum( * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Date: Sat, 6 Dec 2025 14:45:22 +0000 Subject: [PATCH 12/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index cf34ef7feac..603c52fa4c9 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -13,11 +13,11 @@ from packaging.version import Version from xarray.computation import ops +from xarray.computation.apply_ufunc import apply_ufunc from xarray.computation.arithmetic import ( DataArrayGroupbyArithmetic, DatasetGroupbyArithmetic, ) -from xarray.computation.apply_ufunc import apply_ufunc from xarray.core import dtypes, duck_array_ops, nputils from xarray.core._aggregations import ( DataArrayGroupByAggregations, From d8d0eaa2c23e7f7db54e67ecb49093b450a40fd9 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 16:21:11 +0100 Subject: [PATCH 13/74] Update groupby.py --- xarray/core/groupby.py | 48 +++++++++++------------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index cf34ef7feac..345845da163 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -253,9 +253,7 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d( - group: T_Group, obj: T_DataWithCoords -) -> tuple[ +def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, @@ -1221,36 +1219,23 @@ def _flox_scan( obj = self._original_obj - if skipna or ( - skipna is None and isinstance(func, str) and obj.dtype.kind in "cfO" - ): - if "nan" not in func and func not in ["all", "any", "count"]: - func = f"nan{func}" - - # if keep_attrs is None: - # keep_attrs = _get_keep_attrs(default=True) - parsed_dim = self._parse_dim(dim) axis_ = obj.get_axis_num(parsed_dim) axis = (axis_,) if isinstance(axis_, int) else axis_ codes = tuple(g.codes for g in self.groupers) - # g = groupby_scan( - # obj.data, - # *codes, - # func=func, - # expected_groups=None, - # axis=axis, - # dtype=None, - # method=None, - # engine=None, - # ) - # result = obj.copy(data=g) - - # return result + + def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): + if skipna or ( + skipna is None and isinstance(func, str) and obj.dtype.kind in "cfO" + ): + if "nan" not in func: + func = f"nan{func}" + + return groupby_scan(array, *codes, func=func, **kwargs) actual = apply_ufunc( - groupby_scan, + wrapper, obj, *codes, # input_core_dims=input_core_dims, @@ -1267,6 +1252,7 @@ def _flox_scan( ), kwargs=dict( func=func, + skipna=skipna, expected_groups=None, axis=axis, dtype=None, @@ -1277,16 +1263,6 @@ def _flox_scan( return actual - # xarray_reduce( - # obj.drop_vars(non_numeric.keys()), - # *codes, - # dim=parsed_dim, - # expected_groups=expected_groups, - # isbin=False, - # keep_attrs=keep_attrs, - # **kwargs, - # ) - def fillna(self, value: Any) -> T_Xarray: """Fill missing values in this object by group. From 33d136079021896ce9ec48818475e95750424faa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:21:45 +0000 Subject: [PATCH 14/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index a56e37e63f9..755c06d0e9f 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -253,7 +253,9 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ +def _ensure_1d( + group: T_Group, obj: T_DataWithCoords +) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, From c97ae98bb4e0443cfa4063d80b2e673952e713c8 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 16:36:09 +0100 Subject: [PATCH 15/74] sync protocols with each other --- xarray/core/_aggregations.py | 4 ++++ xarray/core/groupby.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index aa4bec25a11..0f4c4a9dd49 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -6650,6 +6650,10 @@ def _flox_reduce( def _flox_scan( self, dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, **kwargs: Any, ) -> DataArray: raise NotImplementedError() diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index a56e37e63f9..85bfb957e9d 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1211,8 +1211,8 @@ def _flox_scan( dim: Dims, *, func: str, - keep_attrs: bool | None = None, skipna: bool | None = None, + keep_attrs: bool | None = None, **kwargs: Any, ) -> DataArray: from flox import groupby_scan From 84f9b4430addb927b32573c088ddb25311fb1844 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 16:46:01 +0100 Subject: [PATCH 16/74] typing --- xarray/core/groupby.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 4aefe5fb8f0..8576cefe1ca 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -253,9 +253,7 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d( - group: T_Group, obj: T_DataWithCoords -) -> tuple[ +def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, @@ -1223,14 +1221,12 @@ def _flox_scan( parsed_dim = self._parse_dim(dim) - axis_ = obj.get_axis_num(parsed_dim) - axis = (axis_,) if isinstance(axis_, int) else axis_ + axis = obj.get_axis_num(parsed_dim) + # axis = (axis_,) if isinstance(axis_, int) else axis_ codes = tuple(g.codes for g in self.groupers) def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): - if skipna or ( - skipna is None and isinstance(func, str) and obj.dtype.kind in "cfO" - ): + if skipna or (skipna is None and obj.dtype.kind in "cfO"): if "nan" not in func: func = f"nan{func}" From 297887709d81fd70cb7d76ccb45456012ea79406 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:46:59 +0000 Subject: [PATCH 17/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 8576cefe1ca..b82c60dca81 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -253,7 +253,9 @@ def to_array(self) -> DataArray: T_Group = Union["T_DataArray", _DummyGroup] -def _ensure_1d(group: T_Group, obj: T_DataWithCoords) -> tuple[ +def _ensure_1d( + group: T_Group, obj: T_DataWithCoords +) -> tuple[ T_Group, T_DataWithCoords, Hashable | None, From 0a9adee78419c3853ef19436d69cf56a21130487 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 19:07:45 +0100 Subject: [PATCH 18/74] add dataset and version requirement --- xarray/core/_aggregations.py | 42 ++++++++++++++++++++++------ xarray/util/generate_aggregations.py | 21 ++++++++++++-- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 0f4c4a9dd49..13ee955b3fd 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3655,6 +3655,17 @@ def _flox_reduce( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -5015,14 +5026,28 @@ def cumsum( Data variables: da (time) float64 48B 1.0 2.0 3.0 3.0 4.0 nan """ - return self.reduce( - duck_array_ops.cumsum, - dim=dim, - skipna=skipna, - numeric_only=True, - keep_attrs=keep_attrs, - **kwargs, - ) + if ( + flox_available + and OPTIONS["use_flox"] + and module_available("flox", minversion="0.10.5") + and contains_only_chunked_or_numpy(self._obj) + ): + return self._flox_scan( + func="cumsum", + dim=dim, + skipna=skipna, + # fill_value=fill_value, + keep_attrs=keep_attrs, + **kwargs, + ) + else: + return self.reduce( + duck_array_ops.cumsum, + dim=dim, + skipna=skipna, + keep_attrs=keep_attrs, + **kwargs, + ) def cumprod( self, @@ -7918,6 +7943,7 @@ def cumsum( if ( flox_available and OPTIONS["use_flox"] + and module_available("flox", minversion="0.10.5") and contains_only_chunked_or_numpy(self._obj) ): return self._flox_scan( diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index e386b96f63d..8c6bc34cfb8 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -15,7 +15,7 @@ import textwrap from dataclasses import dataclass, field -from typing import NamedTuple +from typing import NamedTuple, Literal MODULE_PREAMBLE = '''\ """Mixin classes with reduction operations.""" @@ -132,6 +132,17 @@ def _flox_reduce( dim: Dims, **kwargs: Any, ) -> {obj}: + raise NotImplementedError() + + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: raise NotImplementedError()""" TEMPLATE_REDUCTION_SIGNATURE = ''' @@ -284,6 +295,7 @@ def __init__( see_also_methods=(), min_flox_version=None, additional_notes="", + flox_aggregation_type: Literal["reduce", "scan"] = "reduce", ): self.name = name self.extra_kwargs = extra_kwargs @@ -292,6 +304,7 @@ def __init__( self.see_also_methods = see_also_methods self.min_flox_version = min_flox_version self.additional_notes = additional_notes + self.flox_aggregation_type = flox_aggregation_type if bool_reduce: self.array_method = f"array_{name}" self.np_example_array = ( @@ -444,7 +457,7 @@ def generate_code(self, method, has_keep_attrs): # median isn't enabled yet, because it would break if a single group was present in multiple # chunks. The non-flox code path will just rechunk every group to a single chunk and execute the median - method_is_not_flox_supported = method.name in ("median", "cumsum", "cumprod") + method_is_not_flox_supported = method.name in ("median", "cumprod") if method_is_not_flox_supported: indent = 12 else: @@ -476,7 +489,7 @@ def generate_code(self, method, has_keep_attrs): + f""" and contains_only_chunked_or_numpy(self._obj) ): - return self._flox_reduce( + return self._flox_{method.flox_aggregation_type}( func="{method.name}", dim=dim,{extra_kwargs} # fill_value=fill_value, @@ -537,6 +550,8 @@ def generate_code(self, method, has_keep_attrs): numeric_only=True, see_also_methods=("cumulative",), additional_notes=_CUM_NOTES, + min_flox_version="0.10.5", + flox_aggregation_type="scan", ), Method( "cumprod", From c056d1f8b0ead31241e2f7094073891ce7e41e93 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 18:08:23 +0000 Subject: [PATCH 19/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/util/generate_aggregations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index 8c6bc34cfb8..efe55a5eae5 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -15,7 +15,7 @@ import textwrap from dataclasses import dataclass, field -from typing import NamedTuple, Literal +from typing import Literal, NamedTuple MODULE_PREAMBLE = '''\ """Mixin classes with reduction operations.""" From d4873b992c1561b967dbcde1d09584095293044e Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 19:37:25 +0100 Subject: [PATCH 20/74] Update _aggregations.py --- xarray/core/_aggregations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 13ee955b3fd..e7fb84cde01 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3663,7 +3663,7 @@ def _flox_scan( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> DataArray: + ) -> Dataset: raise NotImplementedError() def count( From 21cbde201ab6edd4596b96318a2075770803023d Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:11:06 +0100 Subject: [PATCH 21/74] Update xarray/core/groupby.py Co-authored-by: Deepak Cherian --- xarray/core/groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index b82c60dca81..8a44e271bb6 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1223,7 +1223,7 @@ def _flox_scan( parsed_dim = self._parse_dim(dim) - axis = obj.get_axis_num(parsed_dim) + axis = obj.transpose(..., *parsed_dim) # axis = (axis_,) if isinstance(axis_, int) else axis_ codes = tuple(g.codes for g in self.groupers) From 4aebc4739cef22d009721cd0fe733bde4eaddf6a Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:14:51 +0100 Subject: [PATCH 22/74] Update groupby.py --- xarray/core/groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 8a44e271bb6..92e8d728775 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1228,7 +1228,7 @@ def _flox_scan( codes = tuple(g.codes for g in self.groupers) def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): - if skipna or (skipna is None and obj.dtype.kind in "cfO"): + if skipna or (skipna is None and array.dtype.kind in "cfO"): if "nan" not in func: func = f"nan{func}" From f4cab24f4f132101b6407d6981cc9efed4a17c21 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:23:32 +0100 Subject: [PATCH 23/74] Update groupby.py --- xarray/core/groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 92e8d728775..a6524125acc 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1216,7 +1216,7 @@ def _flox_scan( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> DataArray: + ) -> T_Xarray: from flox import groupby_scan obj = self._original_obj From 23d9d50cd79e9211ab50fdfbf390f32308938799 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:11:25 +0100 Subject: [PATCH 24/74] Update groupby.py --- xarray/core/groupby.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index a6524125acc..f58a69d88c7 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1220,10 +1220,11 @@ def _flox_scan( from flox import groupby_scan obj = self._original_obj - parsed_dim = self._parse_dim(dim) - axis = obj.transpose(..., *parsed_dim) + obj = obj.transpose(..., *parsed_dim) + axis = range(-len(parsed_dim), 0) + # axis = (axis_,) if isinstance(axis_, int) else axis_ codes = tuple(g.codes for g in self.groupers) From 9b64db2cf3ba19d0578e68e0009d651f6edfc1de Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:11:31 +0100 Subject: [PATCH 25/74] Update generate_aggregations.py --- xarray/util/generate_aggregations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index efe55a5eae5..a6b6d1fb25a 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -142,7 +142,7 @@ def _flox_scan( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> DataArray: + ) -> {obj}: raise NotImplementedError()""" TEMPLATE_REDUCTION_SIGNATURE = ''' From 928b158e181a3f7c973c104e7faca169cc00a3db Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sun, 7 Dec 2025 01:17:04 +0100 Subject: [PATCH 26/74] Renove workaround in test --- xarray/tests/test_groupby.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index e96d8b6828b..f2dbc0a4ce5 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -2568,7 +2568,8 @@ def test_groupby_cumsum() -> None: ) # TODO: Remove drop_vars when GH6528 is fixed # when Dataset.cumsum propagates indexes, and the group variable? - assert_identical(expected.drop_vars(["x", "group_id"]), actual) + # assert_identical(expected.drop_vars(["x", "group_id"]), actual) + assert_identical(expected, actual) actual = ds.foo.groupby("group_id").cumsum(dim="x") expected.coords["group_id"] = ds.group_id From 130f98e9e7657405216db232e0519e557e535e82 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sun, 7 Dec 2025 12:40:30 +0100 Subject: [PATCH 27/74] Update _aggregations.py --- xarray/core/_aggregations.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index e7fb84cde01..28cfc2897bb 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5011,9 +5011,11 @@ def cumsum( da (time) float64 48B 1.0 2.0 3.0 0.0 2.0 nan >>> ds.groupby("labels").cumsum() - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) Date: Sun, 7 Dec 2025 12:43:04 +0100 Subject: [PATCH 28/74] Update _aggregations.py --- xarray/core/_aggregations.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 28cfc2897bb..ad742366077 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5022,9 +5022,11 @@ def cumsum( Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").cumsum(skipna=False) - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) Date: Sun, 7 Dec 2025 12:56:57 +0100 Subject: [PATCH 29/74] Update test_groupby.py --- xarray/tests/test_groupby.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index f2dbc0a4ce5..d79eca3925e 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -16,6 +16,8 @@ from xarray import DataArray, Dataset, Variable, date_range from xarray.core.groupby import _consolidate_slices from xarray.core.types import InterpOptions, ResampleCompatible +from xarray.core.utils import module_available + from xarray.groupers import ( BinGrouper, EncodedGroups, @@ -2566,10 +2568,13 @@ def test_groupby_cumsum() -> None: "group_id": ds.group_id, }, ) - # TODO: Remove drop_vars when GH6528 is fixed - # when Dataset.cumsum propagates indexes, and the group variable? - # assert_identical(expected.drop_vars(["x", "group_id"]), actual) - assert_identical(expected, actual) + + if xr.get_options()["use_flox"] and module_available("flox", minversion="0.10.5"): + assert_identical(expected, actual) + else: + # TODO: Remove drop_vars when GH6528 is fixed + # when Dataset.cumsum propagates indexes, and the group variable? + assert_identical(expected.drop_vars(["x", "group_id"]), actual) actual = ds.foo.groupby("group_id").cumsum(dim="x") expected.coords["group_id"] = ds.group_id From 3bc8dc7b2a69d94d89f5231f10dbcce54b56aa05 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:59:03 +0000 Subject: [PATCH 30/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/tests/test_groupby.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index d79eca3925e..89abaa38568 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -17,7 +17,6 @@ from xarray.core.groupby import _consolidate_slices from xarray.core.types import InterpOptions, ResampleCompatible from xarray.core.utils import module_available - from xarray.groupers import ( BinGrouper, EncodedGroups, From ec8ffd6fd9182b721df9febe65e5219d604122c9 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:01:37 +0100 Subject: [PATCH 31/74] clean ups --- xarray/core/groupby.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index f58a69d88c7..c70da2a16ea 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1219,13 +1219,9 @@ def _flox_scan( ) -> T_Xarray: from flox import groupby_scan - obj = self._original_obj parsed_dim = self._parse_dim(dim) - - obj = obj.transpose(..., *parsed_dim) + obj = self._original_obj.transpose(..., *parsed_dim) axis = range(-len(parsed_dim), 0) - - # axis = (axis_,) if isinstance(axis_, int) else axis_ codes = tuple(g.codes for g in self.groupers) def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): From 07a4d351ee558727d1574a208fae4414fba36f61 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:24:47 +0100 Subject: [PATCH 32/74] Add expected groups, add options --- xarray/core/groupby.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index c70da2a16ea..839800d1fda 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1047,6 +1047,13 @@ def _parse_dim(self, dim: Dims) -> tuple[Hashable, ...]: else: parsed_dim = tuple(dim) + d not in grouper.codes.dims and d not in self._original_obj.dims + for d in parsed_dim + ): + # TODO: Not a helpful error, it's a sanity check that dim actually exist + # either in self.groupers or self._original_obj + raise ValueError(f"cannot reduce over dimensions {dim}.") + return parsed_dim def _flox_reduce( @@ -1111,14 +1118,6 @@ def _flox_reduce( parsed_dim = self._parse_dim(dim) - # Do this so we raise the same error message whether flox is present or not. - # Better to control it here than in flox. - for grouper in self.groupers: - if any( - d not in grouper.codes.dims and d not in obj.dims for d in parsed_dim - ): - raise ValueError(f"cannot reduce over dimensions {dim}.") - has_missing_groups = ( self.encoded.unique_coord.size != self.encoded.full_index.size ) @@ -1224,6 +1223,11 @@ def _flox_scan( axis = range(-len(parsed_dim), 0) codes = tuple(g.codes for g in self.groupers) + # pass RangeIndex as a hint to flox that `by` is already factorized + expected_groups = tuple( + pd.RangeIndex(len(grouper)) for grouper in self.groupers + ) + def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): if skipna or (skipna is None and array.dtype.kind in "cfO"): if "nan" not in func: @@ -1235,26 +1239,18 @@ def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): wrapper, obj, *codes, - # input_core_dims=input_core_dims, - # for xarray's test_groupby_duplicate_coordinate_labels - # exclude_dims=set(dim_tuple), - # output_core_dims=[output_core_dims], dask="allowed", - # dask_gufunc_kwargs=dict( - # output_sizes=output_sizes, - # output_dtypes=[dtype] if dtype is not None else None, - # ), keep_attrs=( _get_keep_attrs(default=True) if keep_attrs is None else keep_attrs ), kwargs=dict( func=func, skipna=skipna, - expected_groups=None, + expected_groups=expected_groups, axis=axis, - dtype=None, - method=None, - engine=None, + dtype=kwargs.get("dtype", None), + method=kwargs.get("method", None), + engine=kwargs.get("engine", None), ), ) From d0f7ed212e3c98e166fb33c3a531c5bd29ba1b98 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:25:06 +0100 Subject: [PATCH 33/74] Update groupby.py --- xarray/core/groupby.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index 839800d1fda..bdfb6eb3c0e 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1047,6 +1047,10 @@ def _parse_dim(self, dim: Dims) -> tuple[Hashable, ...]: else: parsed_dim = tuple(dim) + # Do this so we raise the same error message whether flox is present or not. + # Better to control it here than in flox. + for grouper in self.groupers: + if any( d not in grouper.codes.dims and d not in self._original_obj.dims for d in parsed_dim ): From 098be30fd47cd5e691ef7d0a4119a959408e3ec2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 23:25:38 +0000 Subject: [PATCH 34/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/groupby.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index bdfb6eb3c0e..47841d973f5 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1252,9 +1252,9 @@ def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): skipna=skipna, expected_groups=expected_groups, axis=axis, - dtype=kwargs.get("dtype", None), - method=kwargs.get("method", None), - engine=kwargs.get("engine", None), + dtype=kwargs.get("dtype"), + method=kwargs.get("method"), + engine=kwargs.get("engine"), ), ) From 87d5f77a4d231f52f313891427a21df5db0099c8 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:34:27 +0100 Subject: [PATCH 35/74] expeced_groups not supported in groupby_scan --- xarray/core/groupby.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index bdfb6eb3c0e..0d9ffb88f50 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -1227,11 +1227,6 @@ def _flox_scan( axis = range(-len(parsed_dim), 0) codes = tuple(g.codes for g in self.groupers) - # pass RangeIndex as a hint to flox that `by` is already factorized - expected_groups = tuple( - pd.RangeIndex(len(grouper)) for grouper in self.groupers - ) - def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): if skipna or (skipna is None and array.dtype.kind in "cfO"): if "nan" not in func: @@ -1250,7 +1245,7 @@ def wrapper(array, *by, func: str, skipna: bool | None, **kwargs): kwargs=dict( func=func, skipna=skipna, - expected_groups=expected_groups, + expected_groups=None, # TODO: Should be same as _flox_reduce? axis=axis, dtype=kwargs.get("dtype", None), method=kwargs.get("method", None), From dfe269ac990f452c8df6e1c94821a8251c3b0133 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 19:40:48 +0100 Subject: [PATCH 36/74] Update _aggregations.py --- xarray/core/_aggregations.py | 189 ++++++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 47 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index ad742366077..7fb1662fb87 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5045,13 +5045,14 @@ def cumsum( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.cumsum, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out.assign_coords(self._original_obj.coords) def cumprod( self, @@ -5148,14 +5149,29 @@ def cumprod( Data variables: da (time) float64 48B 1.0 2.0 3.0 0.0 4.0 nan """ - return self.reduce( - duck_array_ops.cumprod, - dim=dim, - skipna=skipna, - numeric_only=True, - keep_attrs=keep_attrs, - **kwargs, - ) + if ( + flox_available + and OPTIONS["use_flox"] + and module_available("flox", minversion="0.10.5") + and contains_only_chunked_or_numpy(self._obj) + ): + return self._flox_scan( + func="cumprod", + dim=dim, + skipna=skipna, + # fill_value=fill_value, + keep_attrs=keep_attrs, + **kwargs, + ) + else: + out = self.reduce( + duck_array_ops.cumprod, + dim=dim, + skipna=skipna, + keep_attrs=keep_attrs, + **kwargs, + ) + return out.assign_coords(self.coords) class DatasetResampleAggregations: @@ -6540,14 +6556,29 @@ def cumsum( Data variables: da (time) float64 48B 1.0 2.0 5.0 5.0 2.0 nan """ - return self.reduce( - duck_array_ops.cumsum, - dim=dim, - skipna=skipna, - numeric_only=True, - keep_attrs=keep_attrs, - **kwargs, - ) + if ( + flox_available + and OPTIONS["use_flox"] + and module_available("flox", minversion="0.10.5") + and contains_only_chunked_or_numpy(self._obj) + ): + return self._flox_scan( + func="cumsum", + dim=dim, + skipna=skipna, + # fill_value=fill_value, + keep_attrs=keep_attrs, + **kwargs, + ) + else: + out = self.reduce( + duck_array_ops.cumsum, + dim=dim, + skipna=skipna, + keep_attrs=keep_attrs, + **kwargs, + ) + return out.assign_coords(self.coords) def cumprod( self, @@ -6644,14 +6675,29 @@ def cumprod( Data variables: da (time) float64 48B 1.0 2.0 6.0 0.0 2.0 nan """ - return self.reduce( - duck_array_ops.cumprod, - dim=dim, - skipna=skipna, - numeric_only=True, - keep_attrs=keep_attrs, - **kwargs, - ) + if ( + flox_available + and OPTIONS["use_flox"] + and module_available("flox", minversion="0.10.5") + and contains_only_chunked_or_numpy(self._obj) + ): + return self._flox_scan( + func="cumprod", + dim=dim, + skipna=skipna, + # fill_value=fill_value, + keep_attrs=keep_attrs, + **kwargs, + ) + else: + out = self.reduce( + duck_array_ops.cumprod, + dim=dim, + skipna=skipna, + keep_attrs=keep_attrs, + **kwargs, + ) + return out.assign_coords(self.coords) class DataArrayGroupByAggregations: @@ -7959,13 +8005,14 @@ def cumsum( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.cumsum, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out.assign_coords(self.coords) def cumprod( self, @@ -8059,13 +8106,29 @@ def cumprod( * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Date: Tue, 9 Dec 2025 20:06:34 +0100 Subject: [PATCH 37/74] Update _aggregations.py --- xarray/core/_aggregations.py | 287 ++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 138 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 7fb1662fb87..00da9eca06c 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3443,6 +3443,7 @@ def median( keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -3666,6 +3667,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -3754,13 +3766,14 @@ def count( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -3850,13 +3863,14 @@ def all( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -3946,13 +3960,14 @@ def any( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -4059,7 +4074,7 @@ def max( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, @@ -4067,6 +4082,7 @@ def max( keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -4173,7 +4189,7 @@ def min( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, @@ -4181,6 +4197,7 @@ def min( keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -4287,7 +4304,7 @@ def mean( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, @@ -4295,6 +4312,7 @@ def mean( keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -4421,7 +4439,7 @@ def prod( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -4430,6 +4448,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -4556,7 +4575,7 @@ def sum( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -4565,6 +4584,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -4688,7 +4708,7 @@ def std( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -4697,6 +4717,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -4820,7 +4841,7 @@ def var( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -4829,6 +4850,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -4922,7 +4944,7 @@ def median( Data variables: da (labels) float64 24B nan 2.0 1.5 """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, @@ -4930,6 +4952,7 @@ def median( keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -5040,6 +5063,7 @@ def cumsum( func="cumsum", dim=dim, skipna=skipna, + numeric_only=True, # fill_value=fill_value, keep_attrs=keep_attrs, **kwargs, @@ -5049,6 +5073,7 @@ def cumsum( duck_array_ops.cumsum, dim=dim, skipna=skipna, + numeric_only=True, keep_attrs=keep_attrs, **kwargs, ) @@ -5149,29 +5174,15 @@ def cumprod( Data variables: da (time) float64 48B 1.0 2.0 3.0 0.0 4.0 nan """ - if ( - flox_available - and OPTIONS["use_flox"] - and module_available("flox", minversion="0.10.5") - and contains_only_chunked_or_numpy(self._obj) - ): - return self._flox_scan( - func="cumprod", - dim=dim, - skipna=skipna, - # fill_value=fill_value, - keep_attrs=keep_attrs, - **kwargs, - ) - else: - out = self.reduce( - duck_array_ops.cumprod, - dim=dim, - skipna=skipna, - keep_attrs=keep_attrs, - **kwargs, - ) - return out.assign_coords(self.coords) + out = self.reduce( + duck_array_ops.cumprod, + dim=dim, + skipna=skipna, + numeric_only=True, + keep_attrs=keep_attrs, + **kwargs, + ) + return out.assign_coords(self._original_obj.coords) class DatasetResampleAggregations: @@ -5284,13 +5295,14 @@ def count( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -5380,13 +5392,14 @@ def all( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -5476,13 +5489,14 @@ def any( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -5589,7 +5603,7 @@ def max( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, @@ -5597,6 +5611,7 @@ def max( keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -5703,7 +5718,7 @@ def min( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, @@ -5711,6 +5726,7 @@ def min( keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -5817,7 +5833,7 @@ def mean( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, @@ -5825,6 +5841,7 @@ def mean( keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -5951,7 +5968,7 @@ def prod( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -5960,6 +5977,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -6086,7 +6104,7 @@ def sum( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -6095,6 +6113,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -6218,7 +6237,7 @@ def std( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -6227,6 +6246,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -6350,7 +6370,7 @@ def var( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -6359,6 +6379,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -6452,7 +6473,7 @@ def median( Data variables: da (time) float64 24B 1.0 2.0 nan """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, @@ -6566,6 +6587,7 @@ def cumsum( func="cumsum", dim=dim, skipna=skipna, + numeric_only=True, # fill_value=fill_value, keep_attrs=keep_attrs, **kwargs, @@ -6575,10 +6597,11 @@ def cumsum( duck_array_ops.cumsum, dim=dim, skipna=skipna, + numeric_only=True, keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self.coords) + return out.assign_coords(self._original_obj.coords) def cumprod( self, @@ -6675,29 +6698,15 @@ def cumprod( Data variables: da (time) float64 48B 1.0 2.0 6.0 0.0 2.0 nan """ - if ( - flox_available - and OPTIONS["use_flox"] - and module_available("flox", minversion="0.10.5") - and contains_only_chunked_or_numpy(self._obj) - ): - return self._flox_scan( - func="cumprod", - dim=dim, - skipna=skipna, - # fill_value=fill_value, - keep_attrs=keep_attrs, - **kwargs, - ) - else: - out = self.reduce( - duck_array_ops.cumprod, - dim=dim, - skipna=skipna, - keep_attrs=keep_attrs, - **kwargs, - ) - return out.assign_coords(self.coords) + out = self.reduce( + duck_array_ops.cumprod, + dim=dim, + skipna=skipna, + numeric_only=True, + keep_attrs=keep_attrs, + **kwargs, + ) + return out.assign_coords(self._original_obj.coords) class DataArrayGroupByAggregations: @@ -6733,6 +6742,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -6815,12 +6835,13 @@ def count( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -6904,12 +6925,13 @@ def all( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -6993,12 +7015,13 @@ def any( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -7097,13 +7120,14 @@ def max( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -7202,13 +7226,14 @@ def min( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -7307,13 +7332,14 @@ def mean( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -7430,7 +7456,7 @@ def prod( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -7438,6 +7464,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -7554,7 +7581,7 @@ def sum( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -7562,6 +7589,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -7675,7 +7703,7 @@ def std( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -7683,6 +7711,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -7796,7 +7825,7 @@ def var( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -7804,6 +7833,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -7890,13 +7920,14 @@ def median( Coordinates: * labels (labels) object 24B 'a' 'b' 'c' """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -8012,7 +8043,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self.coords) + return out.assign_coords(self._original_obj.coords) def cumprod( self, @@ -8106,29 +8137,14 @@ def cumprod( * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Date: Tue, 9 Dec 2025 20:07:12 +0100 Subject: [PATCH 38/74] Update generate_aggregations.py --- xarray/util/generate_aggregations.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index a6b6d1fb25a..df980dade0e 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -295,7 +295,7 @@ def __init__( see_also_methods=(), min_flox_version=None, additional_notes="", - flox_aggregation_type: Literal["reduce", "scan"] = "reduce", + aggregation_type: Literal["reduce", "scan"] = "reduce", ): self.name = name self.extra_kwargs = extra_kwargs @@ -304,7 +304,7 @@ def __init__( self.see_also_methods = see_also_methods self.min_flox_version = min_flox_version self.additional_notes = additional_notes - self.flox_aggregation_type = flox_aggregation_type + self.aggregation_type = aggregation_type if bool_reduce: self.array_method = f"array_{name}" self.np_example_array = ( @@ -468,14 +468,21 @@ def generate_code(self, method, has_keep_attrs): else: extra_kwargs = "" + if method.aggregation_type == "scan": + # Scans retain dimensions. + out_finalized = "out.assign_coords(self._original_obj.coords)" + else: + out_finalized = "out" + if method_is_not_flox_supported: return f"""\ - return self.reduce( + out = self.reduce( duck_array_ops.{method.array_method}, dim=dim,{extra_kwargs} keep_attrs=keep_attrs, **kwargs, - )""" + ) + return {out_finalized}""" min_version_check = f""" and module_available("flox", minversion="{method.min_flox_version}")""" @@ -489,7 +496,7 @@ def generate_code(self, method, has_keep_attrs): + f""" and contains_only_chunked_or_numpy(self._obj) ): - return self._flox_{method.flox_aggregation_type}( + return self._flox_{method.aggregation_type}( func="{method.name}", dim=dim,{extra_kwargs} # fill_value=fill_value, @@ -497,12 +504,13 @@ def generate_code(self, method, has_keep_attrs): **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.{method.array_method}, dim=dim,{extra_kwargs} keep_attrs=keep_attrs, **kwargs, - )""" + ) + return {out_finalized}""" ) @@ -551,7 +559,7 @@ def generate_code(self, method, has_keep_attrs): see_also_methods=("cumulative",), additional_notes=_CUM_NOTES, min_flox_version="0.10.5", - flox_aggregation_type="scan", + aggregation_type="scan", ), Method( "cumprod", @@ -559,6 +567,7 @@ def generate_code(self, method, has_keep_attrs): numeric_only=True, see_also_methods=("cumulative",), additional_notes=_CUM_NOTES, + aggregation_type="scan", ), ) From 55a36abc27e52226530bd966376c86f100854551 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 20:11:40 +0100 Subject: [PATCH 39/74] Update _aggregations.py --- xarray/core/_aggregations.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 00da9eca06c..97a633023ba 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3678,6 +3678,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -6481,6 +6492,7 @@ def median( keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -6753,6 +6765,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -8872,7 +8895,7 @@ def prod( **kwargs, ) else: - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -8880,6 +8903,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, From ff531e1984fd505b46367addab629b26d703411b Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 20:30:05 +0100 Subject: [PATCH 40/74] Update _aggregations.py --- xarray/core/_aggregations.py | 145 ++++++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 46 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 97a633023ba..ce392b2a022 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -104,13 +104,14 @@ def count( Data variables: foo int64 8B 5 """ - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -187,13 +188,14 @@ def all( Data variables: foo bool 1B False """ - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -270,13 +272,14 @@ def any( Data variables: foo bool 1B True """ - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -357,13 +360,8 @@ def max( Use ``skipna`` to control whether NaNs are ignored. >>> dt.max(skipna=False) - - Group: / - Dimensions: () - Data variables: - foo float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, @@ -371,6 +369,7 @@ def max( keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -457,7 +456,7 @@ def min( Data variables: foo float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, @@ -465,6 +464,7 @@ def min( keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -555,7 +555,7 @@ def mean( Data variables: foo float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, @@ -563,6 +563,7 @@ def mean( keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -669,7 +670,7 @@ def prod( Data variables: foo float64 8B 0.0 """ - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -678,6 +679,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -778,13 +780,11 @@ def sum( Specify ``min_count`` for finer control over when NaNs are ignored. >>> dt.sum(skipna=True, min_count=2) - - Group: / Dimensions: () Data variables: foo float64 8B 8.0 """ - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -793,6 +793,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -896,7 +897,7 @@ def std( Data variables: foo float64 8B 1.14 """ - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -905,6 +906,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -1008,7 +1010,7 @@ def var( Data variables: foo float64 8B 1.3 """ - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -1017,6 +1019,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -1107,7 +1110,7 @@ def median( Data variables: foo float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, @@ -1115,6 +1118,7 @@ def median( keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -1212,7 +1216,7 @@ def cumsum( Data variables: foo (time) float64 48B 1.0 3.0 6.0 6.0 8.0 nan """ - return self.reduce( + out = self.reduce( duck_array_ops.cumsum, dim=dim, skipna=skipna, @@ -1220,6 +1224,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) + return out def cumprod( self, @@ -1317,7 +1322,7 @@ def cumprod( Data variables: foo (time) float64 48B 1.0 2.0 6.0 0.0 0.0 nan """ - return self.reduce( + out = self.reduce( duck_array_ops.cumprod, dim=dim, skipna=skipna, @@ -1325,6 +1330,7 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) + return out class DatasetAggregations: @@ -1406,13 +1412,14 @@ def count( Data variables: da int64 8B 5 """ - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -1478,13 +1485,14 @@ def all( Data variables: da bool 1B False """ - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -1550,13 +1558,14 @@ def any( Data variables: da bool 1B True """ - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, numeric_only=False, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -1636,7 +1645,7 @@ def max( Data variables: da float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, @@ -1644,6 +1653,7 @@ def max( keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -1723,7 +1733,7 @@ def min( Data variables: da float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, @@ -1731,6 +1741,7 @@ def min( keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -1810,7 +1821,7 @@ def mean( Data variables: da float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, @@ -1818,6 +1829,7 @@ def mean( keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -1916,7 +1928,7 @@ def prod( Data variables: da float64 8B 0.0 """ - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -1925,6 +1937,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -2023,7 +2036,7 @@ def sum( Data variables: da float64 8B 8.0 """ - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -2032,6 +2045,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -2127,7 +2141,7 @@ def std( Data variables: da float64 8B 1.14 """ - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -2136,6 +2150,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -2231,7 +2246,7 @@ def var( Data variables: da float64 8B 1.3 """ - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -2240,6 +2255,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -2323,7 +2339,7 @@ def median( Data variables: da float64 8B nan """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, @@ -2331,6 +2347,7 @@ def median( keep_attrs=keep_attrs, **kwargs, ) + return out def cumsum( self, @@ -2421,7 +2438,7 @@ def cumsum( Data variables: da (time) float64 48B 1.0 3.0 6.0 6.0 8.0 nan """ - return self.reduce( + out = self.reduce( duck_array_ops.cumsum, dim=dim, skipna=skipna, @@ -2429,6 +2446,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) + return out def cumprod( self, @@ -2519,7 +2537,7 @@ def cumprod( Data variables: da (time) float64 48B 1.0 2.0 6.0 0.0 0.0 nan """ - return self.reduce( + out = self.reduce( duck_array_ops.cumprod, dim=dim, skipna=skipna, @@ -2527,6 +2545,7 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) + return out class DataArrayAggregations: @@ -2603,12 +2622,13 @@ def count( Size: 8B array(5) """ - return self.reduce( + out = self.reduce( duck_array_ops.count, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def all( self, @@ -2669,12 +2689,13 @@ def all( Size: 1B array(False) """ - return self.reduce( + out = self.reduce( duck_array_ops.array_all, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def any( self, @@ -2735,12 +2756,13 @@ def any( Size: 1B array(True) """ - return self.reduce( + out = self.reduce( duck_array_ops.array_any, dim=dim, keep_attrs=keep_attrs, **kwargs, ) + return out def max( self, @@ -2813,13 +2835,14 @@ def max( Size: 8B array(nan) """ - return self.reduce( + out = self.reduce( duck_array_ops.max, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def min( self, @@ -2892,13 +2915,14 @@ def min( Size: 8B array(nan) """ - return self.reduce( + out = self.reduce( duck_array_ops.min, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def mean( self, @@ -2971,13 +2995,14 @@ def mean( Size: 8B array(nan) """ - return self.reduce( + out = self.reduce( duck_array_ops.mean, dim=dim, skipna=skipna, keep_attrs=keep_attrs, **kwargs, ) + return out def prod( self, @@ -3067,7 +3092,7 @@ def prod( Size: 8B array(0.) """ - return self.reduce( + out = self.reduce( duck_array_ops.prod, dim=dim, skipna=skipna, @@ -3075,6 +3100,7 @@ def prod( keep_attrs=keep_attrs, **kwargs, ) + return out def sum( self, @@ -3164,7 +3190,7 @@ def sum( Size: 8B array(8.) """ - return self.reduce( + out = self.reduce( duck_array_ops.sum, dim=dim, skipna=skipna, @@ -3172,6 +3198,7 @@ def sum( keep_attrs=keep_attrs, **kwargs, ) + return out def std( self, @@ -3258,7 +3285,7 @@ def std( Size: 8B array(1.14017543) """ - return self.reduce( + out = self.reduce( duck_array_ops.std, dim=dim, skipna=skipna, @@ -3266,6 +3293,7 @@ def std( keep_attrs=keep_attrs, **kwargs, ) + return out def var( self, @@ -3352,7 +3380,7 @@ def var( Size: 8B array(1.3) """ - return self.reduce( + out = self.reduce( duck_array_ops.var, dim=dim, skipna=skipna, @@ -3360,6 +3388,7 @@ def var( keep_attrs=keep_attrs, **kwargs, ) + return out def median( self, @@ -3436,7 +3465,7 @@ def median( Size: 8B array(nan) """ - return self.reduce( + out = self.reduce( duck_array_ops.median, dim=dim, skipna=skipna, @@ -3531,13 +3560,14 @@ def cumsum( * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -6776,6 +6818,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, From 43aad2e86620f861f4924b4fc30caf8e5046ed47 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 20:33:11 +0100 Subject: [PATCH 41/74] Update _aggregations.py --- xarray/core/_aggregations.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index ce392b2a022..170dbba13cc 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -6796,39 +6796,6 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - def count( self, dim: Dims = None, From 8dfcc564eb6745d35ef5ca757f6fffc730889386 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 20:38:30 +0100 Subject: [PATCH 42/74] Update _aggregations.py --- xarray/core/_aggregations.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 170dbba13cc..0d739aa9e35 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3731,6 +3731,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -6796,6 +6807,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, From 9dac0a4b353fb37300d820c9d200b349c0c36e47 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:08:20 +0100 Subject: [PATCH 43/74] Update generate_aggregations.py --- xarray/util/generate_aggregations.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index df980dade0e..4e256ad786c 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -107,6 +107,17 @@ def _flox_reduce( self, dim: Dims, **kwargs: Any, + ) -> {obj}: + raise NotImplementedError() + + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> {obj}: raise NotImplementedError()""" @@ -529,11 +540,12 @@ def generate_code(self, method, has_keep_attrs): "\n" + 12 * " " + "keep_attrs=keep_attrs," if has_keep_attrs else "" ) return f"""\ - return self.reduce( + out = self.reduce( duck_array_ops.{method.array_method}, dim=dim,{extra_kwargs}{keep_attrs} **kwargs, - )""" + ) + return out""" AGGREGATION_METHODS = ( From 0ba3504d7438222248bc2c7b500a68fd788b1bb3 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:22:10 +0100 Subject: [PATCH 44/74] Update _aggregations.py --- xarray/core/_aggregations.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 0d739aa9e35..6e9dbf5989f 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -9490,8 +9490,8 @@ def cumsum( Size: 48B array([1., 2., 5., 5., 2., 2.]) Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Size: 48B array([ 1., 2., 5., 5., 2., nan]) Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Size: 48B array([1., 2., 6., 0., 2., 2.]) Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Size: 48B array([ 1., 2., 6., 0., 2., nan]) Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 labels (time) Date: Tue, 9 Dec 2025 22:27:49 +0100 Subject: [PATCH 45/74] Update _aggregations.py --- xarray/core/_aggregations.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 6e9dbf5989f..8d66f0fa18c 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5223,18 +5223,22 @@ def cumprod( da (time) float64 48B 1.0 2.0 3.0 0.0 2.0 nan >>> ds.groupby("labels").cumprod() - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").cumprod(skipna=False) - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3ME").cumsum() - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3ME").cumsum(skipna=False) - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3ME").cumprod() - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3ME").cumprod(skipna=False) - Size: 48B + Size: 120B Dimensions: (time: 6) - Dimensions without coordinates: time + Coordinates: + * time (time) datetime64[ns] 48B 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) Date: Tue, 9 Dec 2025 22:33:38 +0100 Subject: [PATCH 46/74] Update _aggregations.py --- xarray/core/_aggregations.py | 44 ------------------------------------ 1 file changed, 44 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 8d66f0fa18c..d7aadb89f4e 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3698,50 +3698,6 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - def count( self, dim: Dims = None, From 7d358b042a3ff7fee85c5b824f598d5da579b452 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:33:54 +0100 Subject: [PATCH 47/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index d7aadb89f4e..08cd827170a 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3698,6 +3698,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From f4fe7a0197749241544e5cca661c4621e965dd23 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:00 +0100 Subject: [PATCH 48/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 08cd827170a..1e2a24efbba 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3709,6 +3709,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 74f1073f7e1c4b352febb292f9c82f6661de78f1 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:05 +0100 Subject: [PATCH 49/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 1e2a24efbba..f782bda09ea 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3720,6 +3720,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 50f620901b790c4657b1bc8988795f15de8d97ee Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:11 +0100 Subject: [PATCH 50/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index f782bda09ea..8d66f0fa18c 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3731,6 +3731,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 87675b24a20033ceab9bd533b7dad7a2f09bcf11 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:18 +0100 Subject: [PATCH 51/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 8d66f0fa18c..eb3f0514f9a 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3742,6 +3742,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 9aee62e8a216d173dd593fa8dc6f7066383fad47 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:25 +0100 Subject: [PATCH 52/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index eb3f0514f9a..4a0b84bd5c3 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3753,6 +3753,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 02ee023b7d5dcc41caf0093515e1942137b41857 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:31 +0100 Subject: [PATCH 53/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 4a0b84bd5c3..173b8847852 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3764,6 +3764,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 82557c4845836412f114ae83b344297ac2b77c5b Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:39 +0100 Subject: [PATCH 54/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 173b8847852..37c5bb49662 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3775,6 +3775,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 9721574c5c89ea126eeb529dcbbff0bfa9fc0e2e Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:48 +0100 Subject: [PATCH 55/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 37c5bb49662..28a48923c4a 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3786,6 +3786,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From e1fba813c2ee02ffc4a19578536289b491b4b205 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:34:56 +0100 Subject: [PATCH 56/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 28a48923c4a..e3f514a040f 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3797,6 +3797,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 5137fd8557281cb4338ae89730ff30f55ee78782 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:06 +0100 Subject: [PATCH 57/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index e3f514a040f..a725d2d6802 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3808,6 +3808,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 59a7f385513476f2c167fdf8c29005e9aafce1db Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:20 +0100 Subject: [PATCH 58/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index a725d2d6802..bfbcfe26385 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3819,6 +3819,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 7f519f031da292abcefd8c3a813ceb229e22dece Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:29 +0100 Subject: [PATCH 59/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index bfbcfe26385..a31c026baed 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3830,6 +3830,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From c4f5f835b679b8dbab8777faf77ccabdb92c470c Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:35 +0100 Subject: [PATCH 60/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index a31c026baed..3d61ced85bc 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3841,6 +3841,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From bf5197d403c4c0dec43cfca33a129c9ef6a420de Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:41 +0100 Subject: [PATCH 61/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 3d61ced85bc..9d4df1a0a66 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3852,6 +3852,17 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> Dataset: + raise NotImplementedError() + def count( self, dim: Dims = None, From 556360098bb6cdc338b762cbb4968f0316a5d36b Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:36:03 +0100 Subject: [PATCH 62/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 9d4df1a0a66..6848cb8cc40 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -6951,6 +6951,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, From 510300dc856f799d4a61034bf6adaa37a1167477 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:36:18 +0100 Subject: [PATCH 63/74] Update _aggregations.py --- xarray/core/_aggregations.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 6848cb8cc40..0e87517b769 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -6962,6 +6962,17 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, From 5fe07dfe4fa4c68ea084ada56dfc231fb55d22bf Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:39:26 +0100 Subject: [PATCH 64/74] Update _aggregations.py --- xarray/core/_aggregations.py | 165 ----------------------------------- 1 file changed, 165 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 0e87517b769..b9cf79ad62b 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -3698,171 +3698,6 @@ def _flox_scan( ) -> Dataset: raise NotImplementedError() - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> Dataset: - raise NotImplementedError() - def count( self, dim: Dims = None, From 293cc1fcc9495ec8d96b5912a28a19bf2b95f293 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:42:11 +0100 Subject: [PATCH 65/74] Update _aggregations.py --- xarray/core/_aggregations.py | 55 +++++++++++++++--------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index b9cf79ad62b..b10e16fcfe5 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5231,6 +5231,17 @@ def _flox_reduce( ) -> Dataset: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, @@ -6775,39 +6786,6 @@ def _flox_scan( ) -> DataArray: raise NotImplementedError() - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - - def _flox_scan( - self, - dim: Dims, - *, - func: str, - skipna: bool | None = None, - keep_attrs: bool | None = None, - **kwargs: Any, - ) -> DataArray: - raise NotImplementedError() - def count( self, dim: Dims = None, @@ -8224,6 +8202,17 @@ def _flox_reduce( ) -> DataArray: raise NotImplementedError() + def _flox_scan( + self, + dim: Dims, + *, + func: str, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, + ) -> DataArray: + raise NotImplementedError() + def count( self, dim: Dims = None, From d9f694c8968df3559a33a219aa2a248859b428a6 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:07:34 +0100 Subject: [PATCH 66/74] Update _aggregations.py --- xarray/core/_aggregations.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index b10e16fcfe5..6d53425b483 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -360,6 +360,11 @@ def max( Use ``skipna`` to control whether NaNs are ignored. >>> dt.max(skipna=False) + + Group: / + Dimensions: () + Data variables: + foo float64 8B nan """ out = self.reduce( duck_array_ops.max, @@ -780,6 +785,8 @@ def sum( Specify ``min_count`` for finer control over when NaNs are ignored. >>> dt.sum(skipna=True, min_count=2) + + Group: / Dimensions: () Data variables: foo float64 8B 8.0 From c9814db7e8f01328761e893d29962d2afe9beb46 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:36:37 +0100 Subject: [PATCH 67/74] Update _aggregations.py --- xarray/core/_aggregations.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 6d53425b483..33fa90cf186 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5105,6 +5105,7 @@ def cumsum( **kwargs, ) return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) def cumprod( self, @@ -5213,7 +5214,7 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) class DatasetResampleAggregations: @@ -5246,7 +5247,7 @@ def _flox_scan( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> DataArray: + ) -> Dataset: raise NotImplementedError() def count( @@ -6648,7 +6649,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) def cumprod( self, @@ -6757,7 +6758,7 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) class DataArrayGroupByAggregations: @@ -8083,7 +8084,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) def cumprod( self, @@ -8184,7 +8185,7 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) class DataArrayResampleAggregations: @@ -9510,7 +9511,7 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) def cumprod( self, @@ -9611,4 +9612,4 @@ def cumprod( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) + return out.assign_coords(self._obj.coords) From 6ed0f9993c4d671c0de300dfa41b4be3b457acce Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:42:09 +0100 Subject: [PATCH 68/74] Update _aggregations.py --- xarray/core/_aggregations.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/core/_aggregations.py b/xarray/core/_aggregations.py index 33fa90cf186..73332f3097c 100644 --- a/xarray/core/_aggregations.py +++ b/xarray/core/_aggregations.py @@ -5104,7 +5104,6 @@ def cumsum( keep_attrs=keep_attrs, **kwargs, ) - return out.assign_coords(self._original_obj.coords) return out.assign_coords(self._obj.coords) def cumprod( From 43a827d02df18a6ca5dac318fec669dbf54414ce Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:53:20 +0100 Subject: [PATCH 69/74] Update test_groupby.py --- xarray/tests/test_groupby.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index 0ccacf2943e..da6746e64f2 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -2596,9 +2596,7 @@ def test_groupby_cumprod() -> None: "group_id": ds.group_id, }, ) - # TODO: Remove drop_vars when GH6528 is fixed - # when Dataset.cumsum propagates indexes, and the group variable? - assert_identical(expected.drop_vars(["x", "group_id"]), actual) + assert_identical(expected, actual) actual = ds.foo.groupby("group_id").cumprod(dim="x") expected.coords["group_id"] = ds.group_id From 8d65562ad606b1c76fca5d9dea4cca4c5c73a173 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:53:31 +0100 Subject: [PATCH 70/74] Update test_groupby.py --- xarray/tests/test_groupby.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index da6746e64f2..f91cd5eacc7 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -2567,13 +2567,7 @@ def test_groupby_cumsum() -> None: "group_id": ds.group_id, }, ) - - if xr.get_options()["use_flox"] and module_available("flox", minversion="0.10.5"): - assert_identical(expected, actual) - else: - # TODO: Remove drop_vars when GH6528 is fixed - # when Dataset.cumsum propagates indexes, and the group variable? - assert_identical(expected.drop_vars(["x", "group_id"]), actual) + assert_identical(expected, actual) actual = ds.foo.groupby("group_id").cumsum(dim="x") expected.coords["group_id"] = ds.group_id From d19bbcaba1a91f67e4fb4c2908d8d8085e807122 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 05:54:27 +0000 Subject: [PATCH 71/74] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/tests/test_groupby.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index f91cd5eacc7..0ee9f4b97ee 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -16,7 +16,6 @@ from xarray import DataArray, Dataset, Variable, date_range from xarray.core.groupby import _consolidate_slices from xarray.core.types import InterpOptions, ResampleCompatible -from xarray.core.utils import module_available from xarray.groupers import ( BinGrouper, EncodedGroups, From acf4022472caa3d1df06362d2d36d9846099839d Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:03:24 +0100 Subject: [PATCH 72/74] Update test_groupby.py --- xarray/tests/test_groupby.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index 0ee9f4b97ee..f1d86911f83 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -2618,9 +2618,7 @@ def test_resample_cumsum(method: str, expected_array: list[float]) -> None: "time": xr.date_range("01-01-2001", freq="ME", periods=6, use_cftime=False), }, ) - # TODO: Remove drop_vars when GH6528 is fixed - # when Dataset.cumsum propagates indexes, and the group variable? - assert_identical(expected.drop_vars(["time"]), actual) + assert_identical(expected, actual) actual = getattr(ds.foo.resample(time="3ME"), method)(dim="time") expected.coords["time"] = ds.time From f263da6fdb1bf247e988749ea510dd73f3f472bf Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:04:35 +0100 Subject: [PATCH 73/74] Update generate_aggregations.py --- xarray/util/generate_aggregations.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xarray/util/generate_aggregations.py b/xarray/util/generate_aggregations.py index 4e256ad786c..c05aa73a350 100644 --- a/xarray/util/generate_aggregations.py +++ b/xarray/util/generate_aggregations.py @@ -4,8 +4,10 @@ Usage: python xarray/util/generate_aggregations.py - pytest --doctest-modules xarray/{core,namedarray}/_aggregations.py --accept || true - pytest --doctest-modules xarray/{core,namedarray}/_aggregations.py + pytest --doctest-modules xarray/core/_aggregations.py --accept + pytest --doctest-modules xarray/core/_aggregations.py + pytest --doctest-modules xarray/namedarray/_aggregations.py --accept + pytest --doctest-modules xarray/namedarray/_aggregations.py This requires [pytest-accept](https://github.com/max-sixty/pytest-accept). The second run of pytest is deliberate, since the first will return an error @@ -481,7 +483,7 @@ def generate_code(self, method, has_keep_attrs): if method.aggregation_type == "scan": # Scans retain dimensions. - out_finalized = "out.assign_coords(self._original_obj.coords)" + out_finalized = "out.assign_coords(self._obj.coords)" else: out_finalized = "out" From e56d0b8638ef894a4dc9b100f1c17d0a32acf726 Mon Sep 17 00:00:00 2001 From: Illviljan <14371165+Illviljan@users.noreply.github.com> Date: Wed, 10 Dec 2025 20:54:04 +0100 Subject: [PATCH 74/74] Update test_groupby.py --- xarray/tests/test_groupby.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index f1d86911f83..51c1a5ba0d4 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -2622,7 +2622,7 @@ def test_resample_cumsum(method: str, expected_array: list[float]) -> None: actual = getattr(ds.foo.resample(time="3ME"), method)(dim="time") expected.coords["time"] = ds.time - assert_identical(expected.drop_vars(["time"]).foo, actual) + assert_identical(expected.foo, actual) def test_groupby_binary_op_regression() -> None: