diff --git a/pandas/core/groupby/base.py b/pandas/core/groupby/base.py index 50248d5af8883..7211fc1b71b54 100644 --- a/pandas/core/groupby/base.py +++ b/pandas/core/groupby/base.py @@ -7,83 +7,8 @@ import collections -from pandas._typing import final - -from pandas.core.dtypes.common import ( - is_list_like, - is_scalar, -) - -from pandas.core.base import PandasObject - OutputKey = collections.namedtuple("OutputKey", ["label", "position"]) - -class ShallowMixin(PandasObject): - _attributes: list[str] = [] - - @final - def _shallow_copy(self, obj, **kwargs): - """ - return a new object with the replacement attributes - """ - if isinstance(obj, self._constructor): - obj = obj.obj - for attr in self._attributes: - if attr not in kwargs: - kwargs[attr] = getattr(self, attr) - return self._constructor(obj, **kwargs) - - -class GotItemMixin(PandasObject): - """ - Provide the groupby facilities to the mixed object. - """ - - _attributes: list[str] - - @final - def _gotitem(self, key, ndim, subset=None): - """ - Sub-classes to define. Return a sliced object. - - Parameters - ---------- - key : string / list of selections - ndim : {1, 2} - requested ndim of result - subset : object, default None - subset to act on - """ - # create a new object to prevent aliasing - if subset is None: - # error: "GotItemMixin" has no attribute "obj" - subset = self.obj # type: ignore[attr-defined] - - # we need to make a shallow copy of ourselves - # with the same groupby - kwargs = {attr: getattr(self, attr) for attr in self._attributes} - - # Try to select from a DataFrame, falling back to a Series - try: - # error: "GotItemMixin" has no attribute "_groupby" - groupby = self._groupby[key] # type: ignore[attr-defined] - except IndexError: - # error: "GotItemMixin" has no attribute "_groupby" - groupby = self._groupby # type: ignore[attr-defined] - - # error: Too many arguments for "GotItemMixin" - # error: Unexpected keyword argument "groupby" for "GotItemMixin" - # error: Unexpected keyword argument "parent" for "GotItemMixin" - self = type(self)( - subset, groupby=groupby, parent=self, **kwargs # type: ignore[call-arg] - ) - self._reset_cache() - if subset.ndim == 2 and (is_scalar(key) and key in subset or is_list_like(key)): - self._selection = key - return self - - # special case to prevent duplicate plots when catching exceptions when # forwarding methods from NDFrames plotting_methods = frozenset(["plot", "hist"]) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index ffe0990a0c8be..58003c10db9e0 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -23,6 +23,7 @@ T, TimedeltaConvertibleTypes, TimestampConvertibleTypes, + final, ) from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError @@ -39,16 +40,15 @@ import pandas.core.algorithms as algos from pandas.core.apply import ResamplerWindowApply -from pandas.core.base import DataError +from pandas.core.base import ( + DataError, + PandasObject, +) import pandas.core.common as com from pandas.core.generic import ( NDFrame, _shared_docs, ) -from pandas.core.groupby.base import ( - GotItemMixin, - ShallowMixin, -) from pandas.core.groupby.generic import SeriesGroupBy from pandas.core.groupby.groupby import ( BaseGroupBy, @@ -86,7 +86,7 @@ _shared_docs_kwargs: dict[str, str] = {} -class Resampler(BaseGroupBy, ShallowMixin): +class Resampler(BaseGroupBy, PandasObject): """ Class for resampling datetimelike data, a groupby-like operation. See aggregate, transform, and apply functions on this object. @@ -141,6 +141,18 @@ def __init__(self, obj, groupby=None, axis=0, kind=None, **kwargs): if self.groupby is not None: self.groupby._set_grouper(self._convert_obj(obj), sort=True) + @final + def _shallow_copy(self, obj, **kwargs): + """ + return a new object with the replacement attributes + """ + if isinstance(obj, self._constructor): + obj = obj.obj + for attr in self._attributes: + if attr not in kwargs: + kwargs[attr] = getattr(self, attr) + return self._constructor(obj, **kwargs) + def __str__(self) -> str: """ Provide a nice str repr of our rolling object. @@ -1018,11 +1030,13 @@ def h(self, _method=method): setattr(Resampler, method, h) -class _GroupByMixin(GotItemMixin): +class _GroupByMixin(PandasObject): """ Provide the groupby facilities. """ + _attributes: list[str] + def __init__(self, obj, *args, **kwargs): parent = kwargs.pop("parent", None) @@ -1064,6 +1078,42 @@ def func(x): _downsample = _apply _groupby_and_aggregate = _apply + @final + def _gotitem(self, key, ndim, subset=None): + """ + Sub-classes to define. Return a sliced object. + + Parameters + ---------- + key : string / list of selections + ndim : {1, 2} + requested ndim of result + subset : object, default None + subset to act on + """ + # create a new object to prevent aliasing + if subset is None: + # error: "GotItemMixin" has no attribute "obj" + subset = self.obj # type: ignore[attr-defined] + + # we need to make a shallow copy of ourselves + # with the same groupby + kwargs = {attr: getattr(self, attr) for attr in self._attributes} + + # Try to select from a DataFrame, falling back to a Series + try: + groupby = self._groupby[key] + except IndexError: + groupby = self._groupby + + self = type(self)(subset, groupby=groupby, parent=self, **kwargs) + self._reset_cache() + if subset.ndim == 2 and ( + lib.is_scalar(key) and key in subset or lib.is_list_like(key) + ): + self._selection = key + return self + class DatetimeIndexResampler(Resampler): @property