diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 2d2f7bbf7092f..0eda80a78ee4f 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -100,7 +100,6 @@ is_list_like, is_named_tuple, is_object_dtype, - is_period_dtype, is_scalar, is_sequence, needs_i8_conversion, @@ -8225,7 +8224,7 @@ def _reduce( dtype_is_dt = np.array( [ - is_datetime64_any_dtype(values.dtype) or is_period_dtype(values.dtype) + is_datetime64_any_dtype(values.dtype) for values in self._iter_column_arrays() ], dtype=bool, @@ -8233,7 +8232,7 @@ def _reduce( if numeric_only is None and name in ["mean", "median"] and dtype_is_dt.any(): warnings.warn( "DataFrame.mean and DataFrame.median with numeric_only=None " - "will include datetime64, datetime64tz, and PeriodDtype columns in a " + "will include datetime64 and datetime64tz columns in a " "future version.", FutureWarning, stacklevel=3, diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index b9ff0a5959c01..32b05872ded3f 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -7,7 +7,7 @@ from pandas._config import get_option -from pandas._libs import NaT, Period, Timedelta, Timestamp, iNaT, lib +from pandas._libs import NaT, Timedelta, Timestamp, iNaT, lib from pandas._typing import ArrayLike, Dtype, Scalar from pandas.compat._optional import import_optional_dependency @@ -353,14 +353,6 @@ def _wrap_results(result, dtype: Dtype, fill_value=None): else: result = result.astype("m8[ns]").view(dtype) - elif isinstance(dtype, PeriodDtype): - if is_float(result) and result.is_integer(): - result = int(result) - if is_integer(result): - result = Period._from_ordinal(result, freq=dtype.freq) - else: - raise NotImplementedError(type(result), result) - return result @@ -516,6 +508,7 @@ def nansum( return _wrap_results(the_sum, dtype) +@disallow(PeriodDtype) @bottleneck_switch() def nanmean(values, axis=None, skipna=True, mask=None): """ @@ -547,7 +540,12 @@ def nanmean(values, axis=None, skipna=True, mask=None): ) dtype_sum = dtype_max dtype_count = np.float64 - if is_integer_dtype(dtype) or needs_i8_conversion(dtype): + # not using needs_i8_conversion because that includes period + if ( + is_integer_dtype(dtype) + or is_datetime64_any_dtype(dtype) + or is_timedelta64_dtype(dtype) + ): dtype_sum = np.float64 elif is_float_dtype(dtype): dtype_sum = dtype diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py index 0255759513e28..75afc59382a75 100644 --- a/pandas/tests/frame/test_analytics.py +++ b/pandas/tests/frame/test_analytics.py @@ -885,16 +885,20 @@ def test_mean_datetimelike_numeric_only_false(self): "A": np.arange(3), "B": pd.date_range("2016-01-01", periods=3), "C": pd.timedelta_range("1D", periods=3), - "D": pd.period_range("2016", periods=3, freq="A"), } ) + # datetime(tz) and timedelta work result = df.mean(numeric_only=False) - expected = pd.Series( - {"A": 1, "B": df.loc[1, "B"], "C": df.loc[1, "C"], "D": df.loc[1, "D"]} - ) + expected = pd.Series({"A": 1, "B": df.loc[1, "B"], "C": df.loc[1, "C"]}) tm.assert_series_equal(result, expected) + # mean of period is not allowed + df["D"] = pd.period_range("2016", periods=3, freq="A") + + with pytest.raises(TypeError, match="reduction operation 'mean' not allowed"): + df.mean(numeric_only=False) + def test_stats_mixed_type(self, float_string_frame): # don't blow up float_string_frame.std(1)