@@ -3843,6 +3843,128 @@ def test_cummin_cummax(self):
3843
3843
expected = pd .Series ([1 , 2 , 1 ], name = 'b' )
3844
3844
tm .assert_series_equal (result , expected )
3845
3845
3846
+ def test_is_increasing_is_decreasing (self ):
3847
+ # GH 17015
3848
+
3849
+ # Basics: strictly increasing (T), strictly decreasing (F),
3850
+ # abs val increasing (F), non-strictly increasing (T)
3851
+ source_dict = {
3852
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3853
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3854
+ 'C' : [1 , 2 , 5 , 3 , 2 , 0 , 4 , 5 , - 6 , 1 , 1 ]}
3855
+ df = pd .DataFrame (source_dict )
3856
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3857
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3858
+ data = [True , False , False , True ],
3859
+ name = 'C' )
3860
+ expected .index .name = 'B'
3861
+ tm .assert_series_equal (result , expected )
3862
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3863
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3864
+ tm .assert_series_equal (result , expected )
3865
+
3866
+ # Test with inf vals
3867
+ source_dict = {
3868
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3869
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3870
+ 'C' : [1 , 2.1 , np .inf , 3 , 2 , np .inf , - np .inf , 5 , 11 , 1 , - np .inf ]}
3871
+ expected .index .name = 'B'
3872
+ df = pd .DataFrame (source_dict )
3873
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3874
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3875
+ data = [True , False , True , False ],
3876
+ name = 'C' )
3877
+ expected .index .name = 'B'
3878
+ tm .assert_series_equal (result , expected )
3879
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3880
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3881
+ tm .assert_series_equal (result , expected )
3882
+
3883
+ # Test with nan vals; should always be False
3884
+ source_dict = {
3885
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3886
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3887
+ 'C' : [1 , 2 , np .nan , 3 , 2 , np .nan , np .nan , 5 , - np .inf , 1 , np .nan ]}
3888
+ df = pd .DataFrame (source_dict )
3889
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3890
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3891
+ data = [False , False , False , False ],
3892
+ name = 'C' )
3893
+ expected .index .name = 'B'
3894
+ tm .assert_series_equal (result , expected )
3895
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3896
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3897
+ tm .assert_series_equal (result , expected )
3898
+
3899
+ # Test with single member groups; should be True except for np.nan
3900
+ source_dict = {
3901
+ 'A' : ['1' , '2' , '3' , '4' ],
3902
+ 'B' : ['a' , 'b' , 'c' , 'd' ],
3903
+ 'C' : [1 , 2 , np .nan , np .inf ]}
3904
+ df = pd .DataFrame (source_dict )
3905
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3906
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3907
+ data = [True , True , False , True ],
3908
+ name = 'C' )
3909
+ expected .index .name = 'B'
3910
+ expected .index .name = 'B'
3911
+ tm .assert_series_equal (result , expected )
3912
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3913
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3914
+ tm .assert_series_equal (result , expected )
3915
+
3916
+ # As above, for .is_monotonic_decreasing()
3917
+ # Basics: strictly decreasing (T), strictly increasing (F),
3918
+ # abs val decreasing (F), non-strictly increasing (T)
3919
+ source_dict = {
3920
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3921
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3922
+ 'C' : [10 , 9 , 7 , 3 , 4 , 5 , - 3 , 2 , 0 , 1 , 1 ]}
3923
+ df = pd .DataFrame (source_dict )
3924
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3925
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3926
+ data = [True , False , False , True ],
3927
+ name = 'C' )
3928
+ expected .index .name = 'B'
3929
+ tm .assert_series_equal (result , expected )
3930
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3931
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3932
+ tm .assert_series_equal (result , expected )
3933
+
3934
+ # Test with inf vals
3935
+ source_dict = {
3936
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3937
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3938
+ 'C' : [np .inf , 1 , - np .inf , np .inf , 2 , - 3 , - np .inf , 5 , - 3 , - np .inf ,
3939
+ - np .inf ]}
3940
+ df = pd .DataFrame (source_dict )
3941
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3942
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3943
+ data = [True , True , False , True ],
3944
+ name = 'C' )
3945
+ expected .index .name = 'B'
3946
+ tm .assert_series_equal (result , expected )
3947
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3948
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3949
+ tm .assert_series_equal (result , expected )
3950
+
3951
+ # Test with nan vals; should always be False
3952
+ source_dict = {
3953
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3954
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3955
+ 'C' : [1 , 2 , np .nan , 3 , 2 , np .nan , np .nan , 5 , - np .inf , 1 , np .nan ]}
3956
+ df = pd .DataFrame (source_dict )
3957
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3958
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3959
+ data = [False , False , False , False ],
3960
+ name = 'C' )
3961
+ expected .index .name = 'B'
3962
+ tm .assert_series_equal (result , expected )
3963
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3964
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3965
+ tm .assert_series_equal (result , expected )
3966
+
3967
+
3846
3968
def test_apply_numeric_coercion_when_datetime (self ):
3847
3969
# In the past, group-by/apply operations have been over-eager
3848
3970
# in converting dtypes to numeric, in the presence of datetime
0 commit comments