@@ -678,7 +678,7 @@ def test_groupby_rolling_nans_in_index(self, rollings, key):
678
678
)
679
679
if key == "index" :
680
680
df = df .set_index ("a" )
681
- with pytest .raises (ValueError , match = f"{ key } must be monotonic " ):
681
+ with pytest .raises (ValueError , match = f"{ key } must not have any NaT values " ):
682
682
df .groupby ("c" ).rolling ("60min" , ** rollings )
683
683
684
684
@pytest .mark .parametrize ("group_keys" , [True , False ])
@@ -922,6 +922,83 @@ def test_nan_and_zero_endpoints(self):
922
922
)
923
923
tm .assert_series_equal (result , expected )
924
924
925
+ def test_groupby_rolling_non_monotonic (self ):
926
+ # GH 43909
927
+
928
+ shuffled = [3 , 0 , 1 , 2 ]
929
+ sec = 1_000
930
+ df = DataFrame (
931
+ [{"t" : Timestamp (2 * x * sec ), "x" : x + 1 , "c" : 42 } for x in shuffled ]
932
+ )
933
+ with pytest .raises (ValueError , match = r".* must be monotonic" ):
934
+ df .groupby ("c" ).rolling (on = "t" , window = "3s" )
935
+
936
+ def test_groupby_monotonic (self ):
937
+
938
+ # GH 15130
939
+ # we don't need to validate monotonicity when grouping
940
+
941
+ # GH 43909 we should raise an error here to match
942
+ # behaviour of non-groupby rolling.
943
+
944
+ data = [
945
+ ["David" , "1/1/2015" , 100 ],
946
+ ["David" , "1/5/2015" , 500 ],
947
+ ["David" , "5/30/2015" , 50 ],
948
+ ["David" , "7/25/2015" , 50 ],
949
+ ["Ryan" , "1/4/2014" , 100 ],
950
+ ["Ryan" , "1/19/2015" , 500 ],
951
+ ["Ryan" , "3/31/2016" , 50 ],
952
+ ["Joe" , "7/1/2015" , 100 ],
953
+ ["Joe" , "9/9/2015" , 500 ],
954
+ ["Joe" , "10/15/2015" , 50 ],
955
+ ]
956
+
957
+ df = DataFrame (data = data , columns = ["name" , "date" , "amount" ])
958
+ df ["date" ] = to_datetime (df ["date" ])
959
+ df = df .sort_values ("date" )
960
+
961
+ expected = (
962
+ df .set_index ("date" )
963
+ .groupby ("name" )
964
+ .apply (lambda x : x .rolling ("180D" )["amount" ].sum ())
965
+ )
966
+ result = df .groupby ("name" ).rolling ("180D" , on = "date" )["amount" ].sum ()
967
+ tm .assert_series_equal (result , expected )
968
+
969
+ def test_datelike_on_monotonic_within_each_group (self ):
970
+ # GH 13966 (similar to #15130, closed by #15175)
971
+
972
+ # superseded by 43909
973
+ # GH 46061: OK if the on is monotonic relative to each each group
974
+
975
+ dates = date_range (start = "2016-01-01 09:30:00" , periods = 20 , freq = "s" )
976
+ df = DataFrame (
977
+ {
978
+ "A" : [1 ] * 20 + [2 ] * 12 + [3 ] * 8 ,
979
+ "B" : np .concatenate ((dates , dates )),
980
+ "C" : np .arange (40 ),
981
+ }
982
+ )
983
+
984
+ expected = (
985
+ df .set_index ("B" ).groupby ("A" ).apply (lambda x : x .rolling ("4s" )["C" ].mean ())
986
+ )
987
+ result = df .groupby ("A" ).rolling ("4s" , on = "B" ).C .mean ()
988
+ tm .assert_series_equal (result , expected )
989
+
990
+ def test_datelike_on_not_monotonic_within_each_group (self ):
991
+ # GH 46061
992
+ df = DataFrame (
993
+ {
994
+ "A" : [1 ] * 3 + [2 ] * 3 ,
995
+ "B" : [Timestamp (year , 1 , 1 ) for year in [2020 , 2021 , 2019 ]] * 2 ,
996
+ "C" : range (6 ),
997
+ }
998
+ )
999
+ with pytest .raises (ValueError , match = "Each group within B must be monotonic." ):
1000
+ df .groupby ("A" ).rolling ("365D" , on = "B" )
1001
+
925
1002
926
1003
class TestExpanding :
927
1004
def setup_method (self ):
0 commit comments