|
21 | 21 | is_scalar,
|
22 | 22 | )
|
23 | 23 | from pandas.core.dtypes.dtypes import register_extension_dtype
|
24 |
| -from pandas.core.dtypes.missing import isna, notna |
| 24 | +from pandas.core.dtypes.missing import isna |
25 | 25 |
|
26 | 26 | from pandas.core import nanops, ops
|
27 | 27 | from pandas.core.ops import invalid_comparison
|
@@ -549,21 +549,23 @@ def _reduce(self, name, skipna=True, **kwargs):
|
549 | 549 | mask = self._mask
|
550 | 550 |
|
551 | 551 | # coerce to a nan-aware float if needed
|
552 |
| - if mask.any(): |
553 |
| - data = self._data.astype("float64") |
554 |
| - # We explicitly use NaN within reductions. |
555 |
| - data[mask] = np.nan |
| 552 | + # (we explicitly use NaN within reductions) |
| 553 | + if self._hasna: |
| 554 | + data = self.to_numpy("float64", na_value=np.nan) |
556 | 555 |
|
557 | 556 | op = getattr(nanops, "nan" + name)
|
558 | 557 | result = op(data, axis=0, skipna=skipna, mask=mask, **kwargs)
|
559 | 558 |
|
| 559 | + if np.isnan(result): |
| 560 | + return libmissing.NA |
| 561 | + |
560 | 562 | # if we have a boolean op, don't coerce
|
561 | 563 | if name in ["any", "all"]:
|
562 | 564 | pass
|
563 | 565 |
|
564 | 566 | # if we have a preservable numeric op,
|
565 | 567 | # provide coercion back to an integer type if possible
|
566 |
| - elif name in ["sum", "min", "max", "prod"] and notna(result): |
| 568 | + elif name in ["sum", "min", "max", "prod"]: |
567 | 569 | int_result = int(result)
|
568 | 570 | if int_result == result:
|
569 | 571 | result = int_result
|
|
0 commit comments