From 1b023dfc9ec45a346e4f67f78d4e61ae8d14732e Mon Sep 17 00:00:00 2001 From: Richard Shadrach <45562402+rhshadrach@users.noreply.github.com> Date: Mon, 14 Nov 2022 23:44:37 -0500 Subject: [PATCH] REGR: Remove groupby's __getattribute__ for nth (#49676) --- doc/source/whatsnew/v1.5.2.rst | 1 + pandas/core/groupby/groupby.py | 23 +++++++++-------------- pandas/core/groupby/indexing.py | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/doc/source/whatsnew/v1.5.2.rst b/doc/source/whatsnew/v1.5.2.rst index 446235d1656dc2..540ca2b12165ce 100644 --- a/doc/source/whatsnew/v1.5.2.rst +++ b/doc/source/whatsnew/v1.5.2.rst @@ -18,6 +18,7 @@ Fixed regressions - Fixed regression in :meth:`DataFrame.plot` preventing :class:`~matplotlib.colors.Colormap` instance from being passed using the ``colormap`` argument if Matplotlib 3.6+ is used (:issue:`49374`) - Fixed regression in :func:`date_range` returning an invalid set of periods for ``CustomBusinessDay`` frequency and ``start`` date with timezone (:issue:`49441`) +- Fixed performance regression in groupby operations (:issue:`49676`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index d10931586d5e04..5a1108c17e6315 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -984,15 +984,6 @@ def __getattr__(self, attr: str): f"'{type(self).__name__}' object has no attribute '{attr}'" ) - def __getattribute__(self, attr: str): - # Intercept nth to allow both call and index - if attr == "nth": - return GroupByNthSelector(self) - elif attr == "nth_actual": - return super().__getattribute__("nth") - else: - return super().__getattribute__(attr) - @final def _op_via_apply(self, name: str, *args, **kwargs): """Compute the result of an operation by using GroupBy's apply.""" @@ -2936,13 +2927,10 @@ def bfill(self, limit=None): return self._fill("bfill", limit=limit) @final + @property @Substitution(name="groupby") @Substitution(see_also=_common_see_also) - def nth( - self, - n: PositionalIndexer | tuple, - dropna: Literal["any", "all", None] = None, - ) -> NDFrameT: + def nth(self) -> GroupByNthSelector: """ Take the nth row from each group if n is an int, otherwise a subset of rows. @@ -3030,6 +3018,13 @@ def nth( Columns: [A, B] Index: [] """ + return GroupByNthSelector(self) + + def _nth( + self, + n: PositionalIndexer | tuple, + dropna: Literal["any", "all", None] = None, + ) -> NDFrameT: if not dropna: mask = self._make_mask_from_positional_indexer(n) diff --git a/pandas/core/groupby/indexing.py b/pandas/core/groupby/indexing.py index be7b7b3369e89c..750097b403f267 100644 --- a/pandas/core/groupby/indexing.py +++ b/pandas/core/groupby/indexing.py @@ -297,7 +297,7 @@ def __call__( n: PositionalIndexer | tuple, dropna: Literal["any", "all", None] = None, ) -> DataFrame | Series: - return self.groupby_object.nth_actual(n, dropna) + return self.groupby_object._nth(n, dropna) def __getitem__(self, n: PositionalIndexer | tuple) -> DataFrame | Series: - return self.groupby_object.nth_actual(n) + return self.groupby_object._nth(n)