@@ -3701,6 +3701,128 @@ def test_cummin_cummax(self):
3701
3701
expected = pd .Series ([1 , 2 , 1 ], name = 'b' )
3702
3702
tm .assert_series_equal (result , expected )
3703
3703
3704
+ def test_is_increasing_is_decreasing (self ):
3705
+ # GH 17015
3706
+
3707
+ # Basics: strictly increasing (T), strictly decreasing (F),
3708
+ # abs val increasing (F), non-strictly increasing (T)
3709
+ source_dict = {
3710
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3711
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3712
+ 'C' : [1 , 2 , 5 , 3 , 2 , 0 , 4 , 5 , - 6 , 1 , 1 ]}
3713
+ df = pd .DataFrame (source_dict )
3714
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3715
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3716
+ data = [True , False , False , True ],
3717
+ name = 'C' )
3718
+ expected .index .name = 'B'
3719
+ tm .assert_series_equal (result , expected )
3720
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3721
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3722
+ tm .assert_series_equal (result , expected )
3723
+
3724
+ # Test with inf vals
3725
+ source_dict = {
3726
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3727
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3728
+ 'C' : [1 , 2.1 , np .inf , 3 , 2 , np .inf , - np .inf , 5 , 11 , 1 , - np .inf ]}
3729
+ expected .index .name = 'B'
3730
+ df = pd .DataFrame (source_dict )
3731
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3732
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3733
+ data = [True , False , True , False ],
3734
+ name = 'C' )
3735
+ expected .index .name = 'B'
3736
+ tm .assert_series_equal (result , expected )
3737
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3738
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3739
+ tm .assert_series_equal (result , expected )
3740
+
3741
+ # Test with nan vals; should always be False
3742
+ source_dict = {
3743
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3744
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3745
+ 'C' : [1 , 2 , np .nan , 3 , 2 , np .nan , np .nan , 5 , - np .inf , 1 , np .nan ]}
3746
+ df = pd .DataFrame (source_dict )
3747
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3748
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3749
+ data = [False , False , False , False ],
3750
+ name = 'C' )
3751
+ expected .index .name = 'B'
3752
+ tm .assert_series_equal (result , expected )
3753
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3754
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3755
+ tm .assert_series_equal (result , expected )
3756
+
3757
+ # Test with single member groups; should be True except for np.nan
3758
+ source_dict = {
3759
+ 'A' : ['1' , '2' , '3' , '4' ],
3760
+ 'B' : ['a' , 'b' , 'c' , 'd' ],
3761
+ 'C' : [1 , 2 , np .nan , np .inf ]}
3762
+ df = pd .DataFrame (source_dict )
3763
+ result = df .groupby (['B' ]).C .is_monotonic_increasing ()
3764
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3765
+ data = [True , True , False , True ],
3766
+ name = 'C' )
3767
+ expected .index .name = 'B'
3768
+ expected .index .name = 'B'
3769
+ tm .assert_series_equal (result , expected )
3770
+ # Also check result equal to manually taking x.is_monotonic_increasing.
3771
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_increasing )
3772
+ tm .assert_series_equal (result , expected )
3773
+
3774
+ # As above, for .is_monotonic_decreasing()
3775
+ # Basics: strictly decreasing (T), strictly increasing (F),
3776
+ # abs val decreasing (F), non-strictly increasing (T)
3777
+ source_dict = {
3778
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3779
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3780
+ 'C' : [10 , 9 , 7 , 3 , 4 , 5 , - 3 , 2 , 0 , 1 , 1 ]}
3781
+ df = pd .DataFrame (source_dict )
3782
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3783
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3784
+ data = [True , False , False , True ],
3785
+ name = 'C' )
3786
+ expected .index .name = 'B'
3787
+ tm .assert_series_equal (result , expected )
3788
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3789
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3790
+ tm .assert_series_equal (result , expected )
3791
+
3792
+ # Test with inf vals
3793
+ source_dict = {
3794
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3795
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3796
+ 'C' : [np .inf , 1 , - np .inf , np .inf , 2 , - 3 , - np .inf , 5 , - 3 , - np .inf ,
3797
+ - np .inf ]}
3798
+ df = pd .DataFrame (source_dict )
3799
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3800
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3801
+ data = [True , True , False , True ],
3802
+ name = 'C' )
3803
+ expected .index .name = 'B'
3804
+ tm .assert_series_equal (result , expected )
3805
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3806
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3807
+ tm .assert_series_equal (result , expected )
3808
+
3809
+ # Test with nan vals; should always be False
3810
+ source_dict = {
3811
+ 'A' : ['1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' , '11' ],
3812
+ 'B' : ['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'c' , 'd' , 'd' ],
3813
+ 'C' : [1 , 2 , np .nan , 3 , 2 , np .nan , np .nan , 5 , - np .inf , 1 , np .nan ]}
3814
+ df = pd .DataFrame (source_dict )
3815
+ result = df .groupby (['B' ]).C .is_monotonic_decreasing ()
3816
+ expected = pd .Series (index = ['a' , 'b' , 'c' , 'd' ],
3817
+ data = [False , False , False , False ],
3818
+ name = 'C' )
3819
+ expected .index .name = 'B'
3820
+ tm .assert_series_equal (result , expected )
3821
+ # Also check result equal to manually taking x.is_monotonic_decreasing.
3822
+ expected = df .groupby ('B' ).C .apply (lambda x : x .is_monotonic_decreasing )
3823
+ tm .assert_series_equal (result , expected )
3824
+
3825
+
3704
3826
def test_apply_numeric_coercion_when_datetime (self ):
3705
3827
# In the past, group-by/apply operations have been over-eager
3706
3828
# in converting dtypes to numeric, in the presence of datetime
0 commit comments