diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index c15948ce877a8..b0f8a0b7a96af 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -2004,8 +2004,6 @@ def mean( return result.__finalize__(self.obj, method="groupby") @final - @Substitution(name="groupby") - @Appender(_common_see_also) def median(self, numeric_only: bool = False): """ Compute median of groups, excluding missing values. @@ -2315,8 +2313,6 @@ def _value_counts( return result.__finalize__(self.obj, method="value_counts") @final - @Substitution(name="groupby") - @Appender(_common_see_also) def sem(self, ddof: int = 1, numeric_only: bool = False): """ Compute standard error of the mean of groups, excluding missing values. @@ -2471,7 +2467,6 @@ def max( ) @final - @Substitution(name="groupby") def first(self, numeric_only: bool = False, min_count: int = -1): """ Compute the first non-null entry of each column. @@ -2542,7 +2537,6 @@ def first(x: Series): ) @final - @Substitution(name="groupby") def last(self, numeric_only: bool = False, min_count: int = -1): """ Compute the last non-null entry of each column. @@ -2602,8 +2596,6 @@ def last(x: Series): ) @final - @Substitution(name="groupby") - @Appender(_common_see_also) def ohlc(self) -> DataFrame: """ Compute open, high, low and close values of a group, excluding missing values. diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 907d6522d3236..ac303e4b1f0bf 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -895,6 +895,74 @@ def asfreq(self, fill_value=None): """ return self._upsample("asfreq", fill_value=fill_value) + def sum( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("sum", args, kwargs) + return self._downsample("sum", numeric_only=numeric_only, min_count=min_count) + + @doc(GroupBy.prod) + def prod( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("prod", args, kwargs) + return self._downsample("prod", numeric_only=numeric_only, min_count=min_count) + + def min( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("min", args, kwargs) + return self._downsample("min", numeric_only=numeric_only, min_count=min_count) + + def max( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("max", args, kwargs) + return self._downsample("max", numeric_only=numeric_only, min_count=min_count) + + @doc(GroupBy.first) + def first( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("first", args, kwargs) + return self._downsample("first", numeric_only=numeric_only, min_count=min_count) + + @doc(GroupBy.last) + def last( + self, + numeric_only: bool = False, + min_count: int = 0, + *args, + **kwargs, + ): + nv.validate_resampler_func("last", args, kwargs) + return self._downsample("last", numeric_only=numeric_only, min_count=min_count) + + @doc(GroupBy.median) + def median(self, numeric_only: bool = False, *args, **kwargs): + nv.validate_resampler_func("median", args, kwargs) + return self._downsample("median", numeric_only=numeric_only) + def mean( self, numeric_only: bool = False, @@ -984,6 +1052,35 @@ def var( nv.validate_resampler_func("var", args, kwargs) return self._downsample("var", ddof=ddof, numeric_only=numeric_only) + @doc(GroupBy.sem) + def sem( + self, + ddof: int = 1, + numeric_only: bool = False, + *args, + **kwargs, + ): + nv.validate_resampler_func("sem", args, kwargs) + return self._downsample("sem", ddof=ddof, numeric_only=numeric_only) + + @doc(GroupBy.ohlc) + def ohlc( + self, + *args, + **kwargs, + ): + nv.validate_resampler_func("ohlc", args, kwargs) + return self._downsample("ohlc") + + @doc(SeriesGroupBy.nunique) + def nunique( + self, + *args, + **kwargs, + ): + nv.validate_resampler_func("nunique", args, kwargs) + return self._downsample("nunique") + @doc(GroupBy.size) def size(self): result = self._downsample("size") @@ -1047,87 +1144,6 @@ def quantile(self, q: float | AnyArrayLike = 0.5, **kwargs): return self._downsample("quantile", q=q, **kwargs) -def _add_downsample_kernel( - name: str, args: tuple[str, ...], docs_class: type = GroupBy -) -> None: - """ - Add a kernel to Resampler. - - Arguments - --------- - name : str - Name of the kernel. - args : tuple - Arguments of the method. - docs_class : type - Class to get kernel docstring from. - """ - assert args in ( - ("numeric_only", "min_count"), - ("numeric_only",), - ("ddof", "numeric_only"), - (), - ) - - # Explicitly provide args rather than args/kwargs for API docs - if args == ("numeric_only", "min_count"): - - def f( - self, - numeric_only: bool = False, - min_count: int = 0, - *args, - **kwargs, - ): - nv.validate_resampler_func(name, args, kwargs) - return self._downsample( - name, numeric_only=numeric_only, min_count=min_count - ) - - elif args == ("numeric_only",): - # error: All conditional function variants must have identical signatures - def f(self, numeric_only: bool = False, *args, **kwargs): # type: ignore[misc] - nv.validate_resampler_func(name, args, kwargs) - return self._downsample(name, numeric_only=numeric_only) - - elif args == ("ddof", "numeric_only"): - # error: All conditional function variants must have identical signatures - def f( # type: ignore[misc] - self, - ddof: int = 1, - numeric_only: bool = False, - *args, - **kwargs, - ): - nv.validate_resampler_func(name, args, kwargs) - return self._downsample(name, ddof=ddof, numeric_only=numeric_only) - - else: - # error: All conditional function variants must have identical signatures - def f( # type: ignore[misc] - self, - *args, - **kwargs, - ): - nv.validate_resampler_func(name, args, kwargs) - return self._downsample(name) - - f.__doc__ = getattr(docs_class, name).__doc__ - setattr(Resampler, name, f) - - -for _method in ["sum", "prod", "min", "max", "first", "last"]: - _add_downsample_kernel(_method, ("numeric_only", "min_count")) -for _method in ["median"]: - _add_downsample_kernel(_method, ("numeric_only",)) -for _method in ["sem"]: - _add_downsample_kernel(_method, ("ddof", "numeric_only")) -for _method in ["ohlc"]: - _add_downsample_kernel(_method, ()) -for _method in ["nunique"]: - _add_downsample_kernel(_method, (), SeriesGroupBy) - - class _GroupByMixin(PandasObject): """ Provide the groupby facilities.