Skip to content

Commit e4c56a4

Browse files
dsaxtonKevin D Smith
authored and
Kevin D Smith
committed
ENH: Implement FloatingArray reductions (pandas-dev#36778)
1 parent 14b2883 commit e4c56a4

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

pandas/core/arrays/floating.py

+13-26
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
from pandas.core.dtypes.dtypes import register_extension_dtype
2626
from pandas.core.dtypes.missing import isna
2727

28-
from pandas.core import nanops, ops
29-
from pandas.core.array_algos import masked_reductions
28+
from pandas.core import ops
3029
from pandas.core.ops import invalid_comparison
3130
from pandas.core.ops.common import unpack_zerodim_and_defer
3231
from pandas.core.tools.numeric import to_numeric
@@ -452,33 +451,21 @@ def cmp_method(self, other):
452451
name = f"__{op.__name__}__"
453452
return set_function_name(cmp_method, name, cls)
454453

455-
def _reduce(self, name: str, skipna: bool = True, **kwargs):
456-
data = self._data
457-
mask = self._mask
458-
459-
if name in {"sum", "prod", "min", "max"}:
460-
op = getattr(masked_reductions, name)
461-
return op(data, mask, skipna=skipna, **kwargs)
462-
463-
# coerce to a nan-aware float if needed
464-
# (we explicitly use NaN within reductions)
465-
if self._hasna:
466-
data = self.to_numpy("float64", na_value=np.nan)
467-
468-
op = getattr(nanops, "nan" + name)
469-
result = op(data, axis=0, skipna=skipna, mask=mask, **kwargs)
454+
def sum(self, skipna=True, min_count=0, **kwargs):
455+
nv.validate_sum((), kwargs)
456+
return super()._reduce("sum", skipna=skipna, min_count=min_count)
470457

471-
if np.isnan(result):
472-
return libmissing.NA
458+
def prod(self, skipna=True, min_count=0, **kwargs):
459+
nv.validate_prod((), kwargs)
460+
return super()._reduce("prod", skipna=skipna, min_count=min_count)
473461

474-
return result
462+
def min(self, skipna=True, **kwargs):
463+
nv.validate_min((), kwargs)
464+
return super()._reduce("min", skipna=skipna)
475465

476-
def sum(self, skipna=True, min_count=0, **kwargs):
477-
nv.validate_sum((), kwargs)
478-
result = masked_reductions.sum(
479-
values=self._data, mask=self._mask, skipna=skipna, min_count=min_count
480-
)
481-
return result
466+
def max(self, skipna=True, **kwargs):
467+
nv.validate_max((), kwargs)
468+
return super()._reduce("max", skipna=skipna)
482469

483470
def _maybe_mask_result(self, result, mask, other, op_name: str):
484471
"""

pandas/tests/arrays/floating/test_function.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ def test_value_counts_empty():
112112

113113
@pytest.mark.parametrize("skipna", [True, False])
114114
@pytest.mark.parametrize("min_count", [0, 4])
115-
def test_floating_array_sum(skipna, min_count):
116-
arr = pd.array([1, 2, 3, None], dtype="Float64")
115+
def test_floating_array_sum(skipna, min_count, dtype):
116+
arr = pd.array([1, 2, 3, None], dtype=dtype)
117117
result = arr.sum(skipna=skipna, min_count=min_count)
118118
if skipna and min_count == 0:
119119
assert result == 6.0
@@ -152,3 +152,26 @@ def test_preserve_dtypes(op):
152152
index=pd.Index(["a", "b"], name="A"),
153153
)
154154
tm.assert_frame_equal(result, expected)
155+
156+
157+
@pytest.mark.parametrize("skipna", [True, False])
158+
@pytest.mark.parametrize("method", ["min", "max"])
159+
def test_floating_array_min_max(skipna, method, dtype):
160+
arr = pd.array([0.0, 1.0, None], dtype=dtype)
161+
func = getattr(arr, method)
162+
result = func(skipna=skipna)
163+
if skipna:
164+
assert result == (0 if method == "min" else 1)
165+
else:
166+
assert result is pd.NA
167+
168+
169+
@pytest.mark.parametrize("skipna", [True, False])
170+
@pytest.mark.parametrize("min_count", [0, 9])
171+
def test_floating_array_prod(skipna, min_count, dtype):
172+
arr = pd.array([1.0, 2.0, None], dtype=dtype)
173+
result = arr.prod(skipna=skipna, min_count=min_count)
174+
if skipna and min_count == 0:
175+
assert result == 2
176+
else:
177+
assert result is pd.NA

0 commit comments

Comments
 (0)