@@ -651,7 +651,7 @@ def test_groupby_rolling_nans_in_index(self, rollings, key):
651
651
)
652
652
if key == "index" :
653
653
df = df .set_index ("a" )
654
- with pytest .raises (ValueError , match = f"{ key } must be monotonic " ):
654
+ with pytest .raises (ValueError , match = f"{ key } must not have any NaT values " ):
655
655
df .groupby ("c" ).rolling ("60min" , ** rollings )
656
656
657
657
@pytest .mark .parametrize ("group_keys" , [True , False ])
@@ -895,6 +895,83 @@ def test_nan_and_zero_endpoints(self):
895
895
)
896
896
tm .assert_series_equal (result , expected )
897
897
898
+ def test_groupby_rolling_non_monotonic (self ):
899
+ # GH 43909
900
+
901
+ shuffled = [3 , 0 , 1 , 2 ]
902
+ sec = 1_000
903
+ df = DataFrame (
904
+ [{"t" : Timestamp (2 * x * sec ), "x" : x + 1 , "c" : 42 } for x in shuffled ]
905
+ )
906
+ with pytest .raises (ValueError , match = r".* must be monotonic" ):
907
+ df .groupby ("c" ).rolling (on = "t" , window = "3s" )
908
+
909
+ def test_groupby_monotonic (self ):
910
+
911
+ # GH 15130
912
+ # we don't need to validate monotonicity when grouping
913
+
914
+ # GH 43909 we should raise an error here to match
915
+ # behaviour of non-groupby rolling.
916
+
917
+ data = [
918
+ ["David" , "1/1/2015" , 100 ],
919
+ ["David" , "1/5/2015" , 500 ],
920
+ ["David" , "5/30/2015" , 50 ],
921
+ ["David" , "7/25/2015" , 50 ],
922
+ ["Ryan" , "1/4/2014" , 100 ],
923
+ ["Ryan" , "1/19/2015" , 500 ],
924
+ ["Ryan" , "3/31/2016" , 50 ],
925
+ ["Joe" , "7/1/2015" , 100 ],
926
+ ["Joe" , "9/9/2015" , 500 ],
927
+ ["Joe" , "10/15/2015" , 50 ],
928
+ ]
929
+
930
+ df = DataFrame (data = data , columns = ["name" , "date" , "amount" ])
931
+ df ["date" ] = to_datetime (df ["date" ])
932
+ df = df .sort_values ("date" )
933
+
934
+ expected = (
935
+ df .set_index ("date" )
936
+ .groupby ("name" )
937
+ .apply (lambda x : x .rolling ("180D" )["amount" ].sum ())
938
+ )
939
+ result = df .groupby ("name" ).rolling ("180D" , on = "date" )["amount" ].sum ()
940
+ tm .assert_series_equal (result , expected )
941
+
942
+ def test_datelike_on_monotonic_within_each_group (self ):
943
+ # GH 13966 (similar to #15130, closed by #15175)
944
+
945
+ # superseded by 43909
946
+ # GH 46061: OK if the on is monotonic relative to each each group
947
+
948
+ dates = date_range (start = "2016-01-01 09:30:00" , periods = 20 , freq = "s" )
949
+ df = DataFrame (
950
+ {
951
+ "A" : [1 ] * 20 + [2 ] * 12 + [3 ] * 8 ,
952
+ "B" : np .concatenate ((dates , dates )),
953
+ "C" : np .arange (40 ),
954
+ }
955
+ )
956
+
957
+ expected = (
958
+ df .set_index ("B" ).groupby ("A" ).apply (lambda x : x .rolling ("4s" )["C" ].mean ())
959
+ )
960
+ result = df .groupby ("A" ).rolling ("4s" , on = "B" ).C .mean ()
961
+ tm .assert_series_equal (result , expected )
962
+
963
+ def test_datelike_on_not_monotonic_within_each_group (self ):
964
+ # GH 46061
965
+ df = DataFrame (
966
+ {
967
+ "A" : [1 ] * 3 + [2 ] * 3 ,
968
+ "B" : [Timestamp (year , 1 , 1 ) for year in [2020 , 2021 , 2019 ]] * 2 ,
969
+ "C" : range (6 ),
970
+ }
971
+ )
972
+ with pytest .raises (ValueError , match = "Each group within B must be monotonic." ):
973
+ df .groupby ("A" ).rolling ("365D" , on = "B" )
974
+
898
975
899
976
class TestExpanding :
900
977
def setup_method (self ):
0 commit comments