@@ -131,6 +131,7 @@ class Resampler(BaseGroupBy, PandasObject):
131
131
132
132
grouper : BinGrouper
133
133
_timegrouper : TimeGrouper
134
+ binner : DatetimeIndex | TimedeltaIndex | PeriodIndex # depends on subclass
134
135
exclusions : frozenset [Hashable ] = frozenset () # for SelectionMixin compat
135
136
136
137
# to the groupby descriptor
@@ -147,15 +148,15 @@ class Resampler(BaseGroupBy, PandasObject):
147
148
148
149
def __init__ (
149
150
self ,
150
- obj : DataFrame | Series ,
151
- groupby : TimeGrouper ,
151
+ obj : NDFrame ,
152
+ timegrouper : TimeGrouper ,
152
153
axis : Axis = 0 ,
153
154
kind = None ,
154
155
* ,
155
156
group_keys : bool | lib .NoDefault = lib .no_default ,
156
157
selection = None ,
157
158
) -> None :
158
- self ._timegrouper = groupby
159
+ self ._timegrouper = timegrouper
159
160
self .keys = None
160
161
self .sort = True
161
162
# error: Incompatible types in assignment (expression has type "Union
@@ -466,7 +467,7 @@ def _groupby_and_aggregate(self, how, *args, **kwargs):
466
467
467
468
return self ._wrap_result (result )
468
469
469
- def _get_resampler_for_grouping (self , groupby , key = None ):
470
+ def _get_resampler_for_grouping (self , groupby : GroupBy , key ):
470
471
"""
471
472
Return the correct class for resampling with groupby.
472
473
"""
@@ -1158,18 +1159,29 @@ class _GroupByMixin(PandasObject):
1158
1159
1159
1160
_attributes : list [str ] # in practice the same as Resampler._attributes
1160
1161
_selection : IndexLabel | None = None
1162
+ _groupby : GroupBy
1163
+ _timegrouper : TimeGrouper
1161
1164
1162
- def __init__ (self , * , parent : Resampler , groupby = None , key = None , ** kwargs ) -> None :
1165
+ def __init__ (
1166
+ self ,
1167
+ * ,
1168
+ parent : Resampler ,
1169
+ groupby : GroupBy ,
1170
+ key = None ,
1171
+ selection : IndexLabel | None = None ,
1172
+ ) -> None :
1163
1173
# reached via ._gotitem and _get_resampler_for_grouping
1164
1174
1175
+ assert isinstance (groupby , GroupBy ), type (groupby )
1176
+
1165
1177
# parent is always a Resampler, sometimes a _GroupByMixin
1166
1178
assert isinstance (parent , Resampler ), type (parent )
1167
1179
1168
1180
# initialize our GroupByMixin object with
1169
1181
# the resampler attributes
1170
1182
for attr in self ._attributes :
1171
- setattr (self , attr , kwargs . get ( attr , getattr (parent , attr ) ))
1172
- self ._selection = kwargs . get ( " selection" )
1183
+ setattr (self , attr , getattr (parent , attr ))
1184
+ self ._selection = selection
1173
1185
1174
1186
self .binner = parent .binner
1175
1187
self .key = key
@@ -1185,7 +1197,7 @@ def _apply(self, f, *args, **kwargs):
1185
1197
"""
1186
1198
1187
1199
def func (x ):
1188
- x = self ._resampler_cls (x , groupby = self ._timegrouper )
1200
+ x = self ._resampler_cls (x , timegrouper = self ._timegrouper )
1189
1201
1190
1202
if isinstance (f , str ):
1191
1203
return getattr (x , f )(** kwargs )
@@ -1217,10 +1229,6 @@ def _gotitem(self, key, ndim, subset=None):
1217
1229
# error: "GotItemMixin" has no attribute "obj"
1218
1230
subset = self .obj # type: ignore[attr-defined]
1219
1231
1220
- # we need to make a shallow copy of ourselves
1221
- # with the same groupby
1222
- kwargs = {attr : getattr (self , attr ) for attr in self ._attributes }
1223
-
1224
1232
# Try to select from a DataFrame, falling back to a Series
1225
1233
try :
1226
1234
if isinstance (key , list ) and self .key not in key and self .key is not None :
@@ -1239,7 +1247,6 @@ def _gotitem(self, key, ndim, subset=None):
1239
1247
groupby = groupby ,
1240
1248
parent = cast (Resampler , self ),
1241
1249
selection = selection ,
1242
- ** kwargs ,
1243
1250
)
1244
1251
return new_rs
1245
1252
@@ -1515,9 +1522,7 @@ def _resampler_cls(self):
1515
1522
return TimedeltaIndexResampler
1516
1523
1517
1524
1518
- def get_resampler (
1519
- obj , kind = None , ** kwds
1520
- ) -> DatetimeIndexResampler | PeriodIndexResampler | TimedeltaIndexResampler :
1525
+ def get_resampler (obj : Series | DataFrame , kind = None , ** kwds ) -> Resampler :
1521
1526
"""
1522
1527
Create a TimeGrouper and return our resampler.
1523
1528
"""
@@ -1529,8 +1534,15 @@ def get_resampler(
1529
1534
1530
1535
1531
1536
def get_resampler_for_grouping (
1532
- groupby , rule , how = None , fill_method = None , limit = None , kind = None , on = None , ** kwargs
1533
- ):
1537
+ groupby : GroupBy ,
1538
+ rule ,
1539
+ how = None ,
1540
+ fill_method = None ,
1541
+ limit = None ,
1542
+ kind = None ,
1543
+ on = None ,
1544
+ ** kwargs ,
1545
+ ) -> Resampler :
1534
1546
"""
1535
1547
Return our appropriate resampler when grouping as well.
1536
1548
"""
@@ -1657,19 +1669,19 @@ def __init__(
1657
1669
1658
1670
super ().__init__ (freq = freq , axis = axis , ** kwargs )
1659
1671
1660
- def _get_resampler (self , obj , kind = None ):
1672
+ def _get_resampler (self , obj : NDFrame , kind = None ) -> Resampler :
1661
1673
"""
1662
1674
Return my resampler or raise if we have an invalid axis.
1663
1675
1664
1676
Parameters
1665
1677
----------
1666
- obj : input object
1678
+ obj : Series or DataFrame
1667
1679
kind : string, optional
1668
1680
'period','timestamp','timedelta' are valid
1669
1681
1670
1682
Returns
1671
1683
-------
1672
- a Resampler
1684
+ Resampler
1673
1685
1674
1686
Raises
1675
1687
------
@@ -1681,15 +1693,23 @@ def _get_resampler(self, obj, kind=None):
1681
1693
ax = self .ax
1682
1694
if isinstance (ax , DatetimeIndex ):
1683
1695
return DatetimeIndexResampler (
1684
- obj , groupby = self , kind = kind , axis = self .axis , group_keys = self .group_keys
1696
+ obj ,
1697
+ timegrouper = self ,
1698
+ kind = kind ,
1699
+ axis = self .axis ,
1700
+ group_keys = self .group_keys ,
1685
1701
)
1686
1702
elif isinstance (ax , PeriodIndex ) or kind == "period" :
1687
1703
return PeriodIndexResampler (
1688
- obj , groupby = self , kind = kind , axis = self .axis , group_keys = self .group_keys
1704
+ obj ,
1705
+ timegrouper = self ,
1706
+ kind = kind ,
1707
+ axis = self .axis ,
1708
+ group_keys = self .group_keys ,
1689
1709
)
1690
1710
elif isinstance (ax , TimedeltaIndex ):
1691
1711
return TimedeltaIndexResampler (
1692
- obj , groupby = self , axis = self .axis , group_keys = self .group_keys
1712
+ obj , timegrouper = self , axis = self .axis , group_keys = self .group_keys
1693
1713
)
1694
1714
1695
1715
raise TypeError (
@@ -1698,10 +1718,12 @@ def _get_resampler(self, obj, kind=None):
1698
1718
f"but got an instance of '{ type (ax ).__name__ } '"
1699
1719
)
1700
1720
1701
- def _get_grouper (self , obj , validate : bool = True ):
1721
+ def _get_grouper (
1722
+ self , obj : NDFrameT , validate : bool = True
1723
+ ) -> tuple [BinGrouper , NDFrameT ]:
1702
1724
# create the resampler and return our binner
1703
1725
r = self ._get_resampler (obj )
1704
- return r .grouper , r .obj
1726
+ return r .grouper , cast ( NDFrameT , r .obj )
1705
1727
1706
1728
def _get_time_bins (self , ax : DatetimeIndex ):
1707
1729
if not isinstance (ax , DatetimeIndex ):
@@ -1766,19 +1788,21 @@ def _get_time_bins(self, ax: DatetimeIndex):
1766
1788
1767
1789
return binner , bins , labels
1768
1790
1769
- def _adjust_bin_edges (self , binner , ax_values ):
1791
+ def _adjust_bin_edges (
1792
+ self , binner : DatetimeIndex , ax_values : npt .NDArray [np .int64 ]
1793
+ ) -> tuple [DatetimeIndex , npt .NDArray [np .int64 ]]:
1770
1794
# Some hacks for > daily data, see #1471, #1458, #1483
1771
1795
1772
1796
if self .freq != "D" and is_superperiod (self .freq , "D" ):
1773
1797
if self .closed == "right" :
1774
1798
# GH 21459, GH 9119: Adjust the bins relative to the wall time
1775
- bin_edges = binner .tz_localize (None )
1776
- bin_edges = (
1777
- bin_edges
1778
- + Timedelta (days = 1 , unit = bin_edges .unit ).as_unit (bin_edges .unit )
1779
- - Timedelta (1 , unit = bin_edges .unit ).as_unit (bin_edges .unit )
1799
+ edges_dti = binner .tz_localize (None )
1800
+ edges_dti = (
1801
+ edges_dti
1802
+ + Timedelta (days = 1 , unit = edges_dti .unit ).as_unit (edges_dti .unit )
1803
+ - Timedelta (1 , unit = edges_dti .unit ).as_unit (edges_dti .unit )
1780
1804
)
1781
- bin_edges = bin_edges .tz_localize (binner .tz ).asi8
1805
+ bin_edges = edges_dti .tz_localize (binner .tz ).asi8
1782
1806
else :
1783
1807
bin_edges = binner .asi8
1784
1808
0 commit comments