Skip to content

Commit

Permalink
REF: Define methods on resample non-dynamically (#50913)
Browse files Browse the repository at this point in the history
* REF: Define methods on resample non-dynamically

* Remove unused ignore
  • Loading branch information
mroeschke authored Jan 25, 2023
1 parent 74b13fa commit a82b8e2
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 89 deletions.
8 changes: 0 additions & 8 deletions pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
178 changes: 97 additions & 81 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit a82b8e2

Please sign in to comment.