@@ -154,3 +154,143 @@ def fn(x):
154154 series = pd .Series ({"a" : list (range (100 ))})
155155
156156 assert isinstance (series .mapply (sum ).iloc [0 ], np .int64 )
157+
158+
159+ def test_rolling_groupby_mapply ():
160+ """Assert RollingGroupby behaviour is equivalent."""
161+ mapply .init (progressbar = False , chunk_size = 1 )
162+
163+ np .random .seed (42 ) # noqa: NPY002
164+ df = pd .DataFrame (
165+ {
166+ "A" : np .random .randint (0 , 100 , 200 ), # noqa: NPY002
167+ "B" : np .random .randint (0 , 100 , 200 ), # noqa: NPY002
168+ "group" : [0 ] * 100 + [1 ] * 100 ,
169+ },
170+ )
171+
172+ # basic RollingGroupby with custom func
173+ pd .testing .assert_frame_equal (
174+ df .groupby ("group" ).rolling (3 ).apply (lambda x : x .sum ()),
175+ df .groupby ("group" ).rolling (3 ).mapply (lambda x : x .sum ()),
176+ )
177+
178+ # min_periods
179+ pd .testing .assert_frame_equal (
180+ df .groupby ("group" ).rolling (5 , min_periods = 2 ).apply (lambda x : x .mean ()),
181+ df .groupby ("group" ).rolling (5 , min_periods = 2 ).mapply (lambda x : x .mean ()),
182+ )
183+
184+ # center=True # noqa: ERA001
185+ pd .testing .assert_frame_equal (
186+ df .groupby ("group" ).rolling (3 , center = True ).apply (lambda x : x .max ()),
187+ df .groupby ("group" ).rolling (3 , center = True ).mapply (lambda x : x .max ()),
188+ )
189+
190+ # column selection (Series result)
191+ pd .testing .assert_series_equal (
192+ df .groupby ("group" )["A" ].rolling (3 ).apply (lambda x : x .sum ()),
193+ df .groupby ("group" )["A" ].rolling (3 ).mapply (lambda x : x .sum ()),
194+ )
195+
196+ # as_index=False # noqa: ERA001
197+ pd .testing .assert_frame_equal (
198+ df .groupby ("group" , as_index = False ).rolling (3 ).apply (lambda x : x .sum ()),
199+ df .groupby ("group" , as_index = False ).rolling (3 ).mapply (lambda x : x .sum ()),
200+ )
201+
202+ # multi-level groupby
203+ df ["group2" ] = list (range (2 )) * 100
204+ pd .testing .assert_frame_equal (
205+ df .groupby (["group" , "group2" ]).rolling (3 ).apply (lambda x : x .sum ()),
206+ df .groupby (["group" , "group2" ]).rolling (3 ).mapply (lambda x : x .sum ()),
207+ )
208+
209+ # time-based rolling with 'on' parameter
210+ df_ts = pd .DataFrame (
211+ {
212+ "A" : np .random .randint (0 , 100 , 200 ), # noqa: NPY002
213+ "dt" : pd .date_range ("2020-01-01" , periods = 200 , freq = "D" ),
214+ "group" : [0 ] * 100 + [1 ] * 100 ,
215+ },
216+ )
217+ pd .testing .assert_frame_equal (
218+ df_ts .groupby ("group" ).rolling ("3D" , on = "dt" ).apply (lambda x : x .sum ()),
219+ df_ts .groupby ("group" ).rolling ("3D" , on = "dt" ).mapply (lambda x : x .sum ()),
220+ )
221+
222+ # empty groupby
223+ pd .testing .assert_frame_equal (
224+ df .iloc [:0 ].groupby ("group" ).rolling (3 ).apply (lambda x : x .sum ()),
225+ df .iloc [:0 ].groupby ("group" ).rolling (3 ).mapply (lambda x : x .sum ()),
226+ )
227+
228+ # n_workers=1 (single-process fallback, no pool spawned)
229+ mapply .init (progressbar = False , chunk_size = 1 , n_workers = 1 )
230+ pd .testing .assert_frame_equal (
231+ df .groupby ("group" ).rolling (3 ).apply (lambda x : x .sum ()),
232+ df .groupby ("group" ).rolling (3 ).mapply (lambda x : x .sum ()),
233+ )
234+
235+
236+ def test_expanding_groupby_mapply ():
237+ """Assert ExpandingGroupby behaviour is equivalent."""
238+ mapply .init (progressbar = False , chunk_size = 1 )
239+
240+ np .random .seed (42 ) # noqa: NPY002
241+ df = pd .DataFrame (
242+ {
243+ "A" : np .random .randint (0 , 100 , 200 ), # noqa: NPY002
244+ "B" : np .random .randint (0 , 100 , 200 ), # noqa: NPY002
245+ "group" : [0 ] * 100 + [1 ] * 100 ,
246+ },
247+ )
248+
249+ # basic ExpandingGroupby with custom func
250+ pd .testing .assert_frame_equal (
251+ df .groupby ("group" ).expanding ().apply (lambda x : x .sum ()),
252+ df .groupby ("group" ).expanding ().mapply (lambda x : x .sum ()),
253+ )
254+
255+ # min_periods
256+ pd .testing .assert_frame_equal (
257+ df .groupby ("group" ).expanding (min_periods = 3 ).apply (lambda x : x .mean ()),
258+ df .groupby ("group" ).expanding (min_periods = 3 ).mapply (lambda x : x .mean ()),
259+ )
260+
261+ # column selection (Series result)
262+ pd .testing .assert_series_equal (
263+ df .groupby ("group" )["A" ].expanding ().apply (lambda x : x .sum ()),
264+ df .groupby ("group" )["A" ].expanding ().mapply (lambda x : x .sum ()),
265+ )
266+
267+ # as_index=False # noqa: ERA001
268+ pd .testing .assert_frame_equal (
269+ df .groupby ("group" , as_index = False ).expanding ().apply (lambda x : x .sum ()),
270+ df .groupby ("group" , as_index = False ).expanding ().mapply (lambda x : x .sum ()),
271+ )
272+
273+ # multi-level groupby
274+ df ["group2" ] = list (range (2 )) * 100
275+ pd .testing .assert_frame_equal (
276+ df .groupby (["group" , "group2" ]).expanding ().apply (lambda x : x .sum ()),
277+ df .groupby (["group" , "group2" ]).expanding ().mapply (lambda x : x .sum ()),
278+ )
279+
280+ # empty groupby
281+ pd .testing .assert_frame_equal (
282+ df .iloc [:0 ].groupby ("group" ).expanding ().apply (lambda x : x .sum ()),
283+ df .iloc [:0 ].groupby ("group" ).expanding ().mapply (lambda x : x .sum ()),
284+ )
285+
286+ # n_workers=1 (single-process fallback)
287+ mapply .init (progressbar = False , chunk_size = 1 , n_workers = 1 )
288+ pd .testing .assert_frame_equal (
289+ df .groupby ("group" ).expanding ().apply (lambda x : x .sum ()),
290+ df .groupby ("group" ).expanding ().mapply (lambda x : x .sum ()),
291+ )
292+
293+ # unsupported window groupby type (e.g. EWM)
294+ mapply .init (progressbar = False , chunk_size = 1 )
295+ with pytest .raises (TypeError , match = "Unsupported window groupby type" ):
296+ df .groupby ("group" ).ewm (span = 3 ).mapply (lambda x : x .sum ())
0 commit comments