Skip to content

Commit 88285f9

Browse files
dcherianandersy005
andauthored
Move Variable aggregations to NamedArray (#8304)
Co-authored-by: Anderson Banihirwe <[email protected]> Co-authored-by: Anderson Banihirwe <[email protected]>
1 parent f895dc1 commit 88285f9

File tree

9 files changed

+1301
-194
lines changed

9 files changed

+1301
-194
lines changed

doc/api-hidden.rst

+30
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,36 @@
351351
IndexVariable.sizes
352352
IndexVariable.values
353353

354+
355+
namedarray.core.NamedArray.all
356+
namedarray.core.NamedArray.any
357+
namedarray.core.NamedArray.attrs
358+
namedarray.core.NamedArray.chunks
359+
namedarray.core.NamedArray.chunksizes
360+
namedarray.core.NamedArray.copy
361+
namedarray.core.NamedArray.count
362+
namedarray.core.NamedArray.cumprod
363+
namedarray.core.NamedArray.cumsum
364+
namedarray.core.NamedArray.data
365+
namedarray.core.NamedArray.dims
366+
namedarray.core.NamedArray.dtype
367+
namedarray.core.NamedArray.get_axis_num
368+
namedarray.core.NamedArray.max
369+
namedarray.core.NamedArray.mean
370+
namedarray.core.NamedArray.median
371+
namedarray.core.NamedArray.min
372+
namedarray.core.NamedArray.nbytes
373+
namedarray.core.NamedArray.ndim
374+
namedarray.core.NamedArray.prod
375+
namedarray.core.NamedArray.reduce
376+
namedarray.core.NamedArray.shape
377+
namedarray.core.NamedArray.size
378+
namedarray.core.NamedArray.sizes
379+
namedarray.core.NamedArray.std
380+
namedarray.core.NamedArray.sum
381+
namedarray.core.NamedArray.var
382+
383+
354384
plot.plot
355385
plot.line
356386
plot.step

xarray/core/arithmetic.py

-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
)
1616
from xarray.core.common import ImplementsArrayReduce, ImplementsDatasetReduce
1717
from xarray.core.ops import (
18-
IncludeCumMethods,
1918
IncludeNumpySameMethods,
2019
IncludeReduceMethods,
2120
)
@@ -99,8 +98,6 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
9998

10099
class VariableArithmetic(
101100
ImplementsArrayReduce,
102-
IncludeReduceMethods,
103-
IncludeCumMethods,
104101
IncludeNumpySameMethods,
105102
SupportsArithmetic,
106103
VariableOpsMixin,

xarray/core/dataset.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6280,7 +6280,7 @@ def dropna(
62806280
array = self._variables[k]
62816281
if dim in array.dims:
62826282
dims = [d for d in array.dims if d != dim]
6283-
count += np.asarray(array.count(dims)) # type: ignore[attr-defined]
6283+
count += np.asarray(array.count(dims))
62846284
size += math.prod([self.dims[d] for d in dims])
62856285

62866286
if thresh is not None:

xarray/core/formatting_html.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def _load_static_files():
2828
]
2929

3030

31-
def short_data_repr_html(array):
31+
def short_data_repr_html(array) -> str:
3232
"""Format "data" for DataArray and Variable."""
3333
internal_data = getattr(array, "variable", array)._data
3434
if hasattr(internal_data, "_repr_html_"):
@@ -37,7 +37,7 @@ def short_data_repr_html(array):
3737
return f"<pre>{text}</pre>"
3838

3939

40-
def format_dims(dims, dims_with_index):
40+
def format_dims(dims, dims_with_index) -> str:
4141
if not dims:
4242
return ""
4343

@@ -53,7 +53,7 @@ def format_dims(dims, dims_with_index):
5353
return f"<ul class='xr-dim-list'>{dims_li}</ul>"
5454

5555

56-
def summarize_attrs(attrs):
56+
def summarize_attrs(attrs) -> str:
5757
attrs_dl = "".join(
5858
f"<dt><span>{escape(str(k))} :</span></dt>" f"<dd>{escape(str(v))}</dd>"
5959
for k, v in attrs.items()
@@ -62,7 +62,7 @@ def summarize_attrs(attrs):
6262
return f"<dl class='xr-attrs'>{attrs_dl}</dl>"
6363

6464

65-
def _icon(icon_name):
65+
def _icon(icon_name) -> str:
6666
# icon_name should be defined in xarray/static/html/icon-svg-inline.html
6767
return (
6868
f"<svg class='icon xr-{icon_name}'>"
@@ -72,7 +72,7 @@ def _icon(icon_name):
7272
)
7373

7474

75-
def summarize_variable(name, var, is_index=False, dtype=None):
75+
def summarize_variable(name, var, is_index=False, dtype=None) -> str:
7676
variable = var.variable if hasattr(var, "variable") else var
7777

7878
cssclass_idx = " class='xr-has-index'" if is_index else ""
@@ -109,7 +109,7 @@ def summarize_variable(name, var, is_index=False, dtype=None):
109109
)
110110

111111

112-
def summarize_coords(variables):
112+
def summarize_coords(variables) -> str:
113113
li_items = []
114114
for k, v in variables.items():
115115
li_content = summarize_variable(k, v, is_index=k in variables.xindexes)
@@ -120,7 +120,7 @@ def summarize_coords(variables):
120120
return f"<ul class='xr-var-list'>{vars_li}</ul>"
121121

122122

123-
def summarize_vars(variables):
123+
def summarize_vars(variables) -> str:
124124
vars_li = "".join(
125125
f"<li class='xr-var-item'>{summarize_variable(k, v)}</li>"
126126
for k, v in variables.items()
@@ -129,14 +129,14 @@ def summarize_vars(variables):
129129
return f"<ul class='xr-var-list'>{vars_li}</ul>"
130130

131131

132-
def short_index_repr_html(index):
132+
def short_index_repr_html(index) -> str:
133133
if hasattr(index, "_repr_html_"):
134134
return index._repr_html_()
135135

136136
return f"<pre>{escape(repr(index))}</pre>"
137137

138138

139-
def summarize_index(coord_names, index):
139+
def summarize_index(coord_names, index) -> str:
140140
name = "<br>".join([escape(str(n)) for n in coord_names])
141141

142142
index_id = f"index-{uuid.uuid4()}"
@@ -155,7 +155,7 @@ def summarize_index(coord_names, index):
155155
)
156156

157157

158-
def summarize_indexes(indexes):
158+
def summarize_indexes(indexes) -> str:
159159
indexes_li = "".join(
160160
f"<li class='xr-var-item'>{summarize_index(v, i)}</li>"
161161
for v, i in indexes.items()
@@ -165,7 +165,7 @@ def summarize_indexes(indexes):
165165

166166
def collapsible_section(
167167
name, inline_details="", details="", n_items=None, enabled=True, collapsed=False
168-
):
168+
) -> str:
169169
# "unique" id to expand/collapse the section
170170
data_id = "section-" + str(uuid.uuid4())
171171

@@ -187,7 +187,7 @@ def collapsible_section(
187187

188188
def _mapping_section(
189189
mapping, name, details_func, max_items_collapse, expand_option_name, enabled=True
190-
):
190+
) -> str:
191191
n_items = len(mapping)
192192
expanded = _get_boolean_with_default(
193193
expand_option_name, n_items < max_items_collapse
@@ -203,15 +203,15 @@ def _mapping_section(
203203
)
204204

205205

206-
def dim_section(obj):
206+
def dim_section(obj) -> str:
207207
dim_list = format_dims(obj.dims, obj.xindexes.dims)
208208

209209
return collapsible_section(
210210
"Dimensions", inline_details=dim_list, enabled=False, collapsed=True
211211
)
212212

213213

214-
def array_section(obj):
214+
def array_section(obj) -> str:
215215
# "unique" id to expand/collapse the section
216216
data_id = "section-" + str(uuid.uuid4())
217217
collapsed = (
@@ -296,7 +296,7 @@ def _obj_repr(obj, header_components, sections):
296296
)
297297

298298

299-
def array_repr(arr):
299+
def array_repr(arr) -> str:
300300
dims = OrderedDict((k, v) for k, v in zip(arr.dims, arr.shape))
301301
if hasattr(arr, "xindexes"):
302302
indexed_dims = arr.xindexes.dims
@@ -326,7 +326,7 @@ def array_repr(arr):
326326
return _obj_repr(arr, header_components, sections)
327327

328328

329-
def dataset_repr(ds):
329+
def dataset_repr(ds) -> str:
330330
obj_type = f"xarray.{type(ds).__name__}"
331331

332332
header_components = [f"<div class='xr-obj-type'>{escape(obj_type)}</div>"]

xarray/core/ops.py

-25
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
"var",
5454
"median",
5555
]
56-
NAN_CUM_METHODS = ["cumsum", "cumprod"]
5756
# TODO: wrap take, dot, sort
5857

5958

@@ -263,20 +262,6 @@ def inject_reduce_methods(cls):
263262
setattr(cls, name, func)
264263

265264

266-
def inject_cum_methods(cls):
267-
methods = [(name, getattr(duck_array_ops, name), True) for name in NAN_CUM_METHODS]
268-
for name, f, include_skipna in methods:
269-
numeric_only = getattr(f, "numeric_only", False)
270-
func = cls._reduce_method(f, include_skipna, numeric_only)
271-
func.__name__ = name
272-
func.__doc__ = _CUM_DOCSTRING_TEMPLATE.format(
273-
name=name,
274-
cls=cls.__name__,
275-
extra_args=cls._cum_extra_args_docstring.format(name=name),
276-
)
277-
setattr(cls, name, func)
278-
279-
280265
def op_str(name):
281266
return f"__{name}__"
282267

@@ -316,16 +301,6 @@ def __init_subclass__(cls, **kwargs):
316301
inject_reduce_methods(cls)
317302

318303

319-
class IncludeCumMethods:
320-
__slots__ = ()
321-
322-
def __init_subclass__(cls, **kwargs):
323-
super().__init_subclass__(**kwargs)
324-
325-
if getattr(cls, "_reduce_method", None):
326-
inject_cum_methods(cls)
327-
328-
329304
class IncludeNumpySameMethods:
330305
__slots__ = ()
331306

xarray/core/variable.py

+15-53
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import math
66
import numbers
77
import warnings
8-
from collections.abc import Hashable, Iterable, Mapping, Sequence
8+
from collections.abc import Hashable, Mapping, Sequence
99
from datetime import timedelta
1010
from functools import partial
1111
from typing import TYPE_CHECKING, Any, Callable, Literal, NoReturn, cast
@@ -1704,7 +1704,7 @@ def clip(self, min=None, max=None):
17041704

17051705
return apply_ufunc(np.clip, self, min, max, dask="allowed")
17061706

1707-
def reduce(
1707+
def reduce( # type: ignore[override]
17081708
self,
17091709
func: Callable[..., Any],
17101710
dim: Dims = None,
@@ -1745,59 +1745,21 @@ def reduce(
17451745
Array with summarized data and the indicated dimension(s)
17461746
removed.
17471747
"""
1748-
if dim == ...:
1749-
dim = None
1750-
if dim is not None and axis is not None:
1751-
raise ValueError("cannot supply both 'axis' and 'dim' arguments")
1752-
1753-
if dim is not None:
1754-
axis = self.get_axis_num(dim)
1755-
1756-
with warnings.catch_warnings():
1757-
warnings.filterwarnings(
1758-
"ignore", r"Mean of empty slice", category=RuntimeWarning
1759-
)
1760-
if axis is not None:
1761-
if isinstance(axis, tuple) and len(axis) == 1:
1762-
# unpack axis for the benefit of functions
1763-
# like np.argmin which can't handle tuple arguments
1764-
axis = axis[0]
1765-
data = func(self.data, axis=axis, **kwargs)
1766-
else:
1767-
data = func(self.data, **kwargs)
1768-
1769-
if getattr(data, "shape", ()) == self.shape:
1770-
dims = self.dims
1771-
else:
1772-
removed_axes: Iterable[int]
1773-
if axis is None:
1774-
removed_axes = range(self.ndim)
1775-
else:
1776-
removed_axes = np.atleast_1d(axis) % self.ndim
1777-
if keepdims:
1778-
# Insert np.newaxis for removed dims
1779-
slices = tuple(
1780-
np.newaxis if i in removed_axes else slice(None, None)
1781-
for i in range(self.ndim)
1782-
)
1783-
if getattr(data, "shape", None) is None:
1784-
# Reduce has produced a scalar value, not an array-like
1785-
data = np.asanyarray(data)[slices]
1786-
else:
1787-
data = data[slices]
1788-
dims = self.dims
1789-
else:
1790-
dims = tuple(
1791-
adim for n, adim in enumerate(self.dims) if n not in removed_axes
1792-
)
1748+
keep_attrs_ = (
1749+
_get_keep_attrs(default=False) if keep_attrs is None else keep_attrs
1750+
)
17931751

1794-
if keep_attrs is None:
1795-
keep_attrs = _get_keep_attrs(default=False)
1796-
attrs = self._attrs if keep_attrs else None
1752+
# Noe that the call order for Variable.mean is
1753+
# Variable.mean -> NamedArray.mean -> Variable.reduce
1754+
# -> NamedArray.reduce
1755+
result = super().reduce(
1756+
func=func, dim=dim, axis=axis, keepdims=keepdims, **kwargs
1757+
)
17971758

1798-
# We need to return `Variable` rather than the type of `self` at the moment, ref
1799-
# #8216
1800-
return Variable(dims, data, attrs=attrs)
1759+
# return Variable always to support IndexVariable
1760+
return Variable(
1761+
result.dims, result._data, attrs=result._attrs if keep_attrs_ else None
1762+
)
18011763

18021764
@classmethod
18031765
def concat(

0 commit comments

Comments
 (0)