Skip to content

Commit 2724350

Browse files
mroeschkejreback
andauthoredFeb 25, 2021
BUG/REF: Refactor BaseWindowIndex so groupby.apply has a consistent index output (pandas-dev#39765)
* Remove _groupby object from class * Add test that groupby apply is not affected * Remove unnecessary groupby subclasses * Supress private variables in repr * Don't have window classes accept kwargs * Add whatsnew * Remove unused constructor * Just user the grouper * Make expected index instead Co-authored-by: Jeff Reback <[email protected]>
1 parent ac12caf commit 2724350

File tree

8 files changed

+143
-83
lines changed

8 files changed

+143
-83
lines changed
 

‎doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ Groupby/resample/rolling
443443
- Bug in :meth:`.GroupBy.mean`, :meth:`.GroupBy.median` and :meth:`DataFrame.pivot_table` not propagating metadata (:issue:`28283`)
444444
- Bug in :meth:`Series.rolling` and :meth:`DataFrame.rolling` not calculating window bounds correctly when window is an offset and dates are in descending order (:issue:`40002`)
445445
- Bug in :class:`SeriesGroupBy` and :class:`DataFrameGroupBy` on an empty ``Series`` or ``DataFrame`` would lose index, columns, and/or data types when directly using the methods ``idxmax``, ``idxmin``, ``mad``, ``min``, ``max``, ``sum``, ``prod``, and ``skew`` or using them through ``apply``, ``aggregate``, or ``resample`` (:issue:`26411`)
446+
- Bug in :meth:`DataFrameGroupBy.apply` where a :class:`MultiIndex` would be created instead of an :class:`Index` if a :class:`:meth:`core.window.rolling.RollingGroupby` object was created (:issue:`39732`)
446447
- Bug in :meth:`DataFrameGroupBy.sample` where error was raised when ``weights`` was specified and the index was an :class:`Int64Index` (:issue:`39927`)
447448
- Bug in :meth:`DataFrameGroupBy.aggregate` and :meth:`.Resampler.aggregate` would sometimes raise ``SpecificationError`` when passed a dictionary and columns were missing; will now always raise a ``KeyError`` instead (:issue:`40004`)
448449
-

‎pandas/core/groupby/base.py

+2-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""
66
import collections
77
from typing import List
8-
import warnings
98

109
from pandas._typing import final
1110

@@ -31,10 +30,7 @@ def _shallow_copy(self, obj, **kwargs):
3130
obj = obj.obj
3231
for attr in self._attributes:
3332
if attr not in kwargs:
34-
# TODO: Remove once win_type deprecation is enforced
35-
with warnings.catch_warnings():
36-
warnings.filterwarnings("ignore", "win_type", FutureWarning)
37-
kwargs[attr] = getattr(self, attr)
33+
kwargs[attr] = getattr(self, attr)
3834
return self._constructor(obj, **kwargs)
3935

4036

@@ -65,10 +61,7 @@ def _gotitem(self, key, ndim, subset=None):
6561

6662
# we need to make a shallow copy of ourselves
6763
# with the same groupby
68-
# TODO: Remove once win_type deprecation is enforced
69-
with warnings.catch_warnings():
70-
warnings.filterwarnings("ignore", "win_type", FutureWarning)
71-
kwargs = {attr: getattr(self, attr) for attr in self._attributes}
64+
kwargs = {attr: getattr(self, attr) for attr in self._attributes}
7265

7366
# Try to select from a DataFrame, falling back to a Series
7467
try:

‎pandas/core/groupby/groupby.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -1918,7 +1918,12 @@ def rolling(self, *args, **kwargs):
19181918
"""
19191919
from pandas.core.window import RollingGroupby
19201920

1921-
return RollingGroupby(self, *args, **kwargs)
1921+
return RollingGroupby(
1922+
self._selected_obj,
1923+
*args,
1924+
_grouper=self.grouper,
1925+
**kwargs,
1926+
)
19221927

19231928
@final
19241929
@Substitution(name="groupby")
@@ -1930,7 +1935,12 @@ def expanding(self, *args, **kwargs):
19301935
"""
19311936
from pandas.core.window import ExpandingGroupby
19321937

1933-
return ExpandingGroupby(self, *args, **kwargs)
1938+
return ExpandingGroupby(
1939+
self._selected_obj,
1940+
*args,
1941+
_grouper=self.grouper,
1942+
**kwargs,
1943+
)
19341944

19351945
@final
19361946
@Substitution(name="groupby")
@@ -1941,7 +1951,12 @@ def ewm(self, *args, **kwargs):
19411951
"""
19421952
from pandas.core.window import ExponentialMovingWindowGroupby
19431953

1944-
return ExponentialMovingWindowGroupby(self, *args, **kwargs)
1954+
return ExponentialMovingWindowGroupby(
1955+
self._selected_obj,
1956+
*args,
1957+
_grouper=self.grouper,
1958+
**kwargs,
1959+
)
19451960

19461961
@final
19471962
def _fill(self, direction, limit=None):

‎pandas/core/window/ewm.py

+20-13
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,15 @@ class ExponentialMovingWindow(BaseWindow):
213213
4 3.233686
214214
"""
215215

216-
_attributes = ["com", "min_periods", "adjust", "ignore_na", "axis"]
216+
_attributes = [
217+
"com",
218+
"min_periods",
219+
"adjust",
220+
"ignore_na",
221+
"axis",
222+
"halflife",
223+
"times",
224+
]
217225

218226
def __init__(
219227
self,
@@ -227,17 +235,18 @@ def __init__(
227235
ignore_na: bool = False,
228236
axis: int = 0,
229237
times: Optional[Union[str, np.ndarray, FrameOrSeries]] = None,
230-
**kwargs,
231238
):
232-
self.obj = obj
233-
self.min_periods = max(int(min_periods), 1)
239+
super().__init__(
240+
obj=obj,
241+
min_periods=max(int(min_periods), 1),
242+
on=None,
243+
center=False,
244+
closed=None,
245+
method="single",
246+
axis=axis,
247+
)
234248
self.adjust = adjust
235249
self.ignore_na = ignore_na
236-
self.axis = axis
237-
self.on = None
238-
self.center = False
239-
self.closed = None
240-
self.method = "single"
241250
if times is not None:
242251
if isinstance(times, str):
243252
times = self._selected_obj[times]
@@ -556,9 +565,7 @@ class ExponentialMovingWindowGroupby(BaseWindowGroupby, ExponentialMovingWindow)
556565
Provide an exponential moving window groupby implementation.
557566
"""
558567

559-
@property
560-
def _constructor(self):
561-
return ExponentialMovingWindow
568+
_attributes = ExponentialMovingWindow._attributes + BaseWindowGroupby._attributes
562569

563570
def _get_window_indexer(self) -> GroupbyIndexer:
564571
"""
@@ -569,7 +576,7 @@ def _get_window_indexer(self) -> GroupbyIndexer:
569576
GroupbyIndexer
570577
"""
571578
window_indexer = GroupbyIndexer(
572-
groupby_indicies=self._groupby.indices,
579+
groupby_indicies=self._grouper.indices,
573580
window_indexer=ExponentialMovingWindowIndexer,
574581
)
575582
return window_indexer

‎pandas/core/window/expanding.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ class Expanding(RollingAndExpandingMixin):
9494

9595
_attributes = ["min_periods", "center", "axis", "method"]
9696

97-
def __init__(
98-
self, obj, min_periods=1, center=None, axis=0, method="single", **kwargs
99-
):
97+
def __init__(self, obj, min_periods=1, center=None, axis=0, method="single"):
10098
super().__init__(
10199
obj=obj, min_periods=min_periods, center=center, axis=axis, method=method
102100
)
@@ -629,9 +627,7 @@ class ExpandingGroupby(BaseWindowGroupby, Expanding):
629627
Provide a expanding groupby implementation.
630628
"""
631629

632-
@property
633-
def _constructor(self):
634-
return Expanding
630+
_attributes = Expanding._attributes + BaseWindowGroupby._attributes
635631

636632
def _get_window_indexer(self) -> GroupbyIndexer:
637633
"""
@@ -642,7 +638,7 @@ def _get_window_indexer(self) -> GroupbyIndexer:
642638
GroupbyIndexer
643639
"""
644640
window_indexer = GroupbyIndexer(
645-
groupby_indicies=self._groupby.indices,
641+
groupby_indicies=self._grouper.indices,
646642
window_indexer=ExpandingIndexer,
647643
)
648644
return window_indexer

0 commit comments

Comments
 (0)
Please sign in to comment.