Skip to content Skip to sidebar Skip to footer

Pandas Dataframe: Check If Data Is Monotonically Decreasing

I have a pandas dataframe like this: Balance Jan Feb Mar Apr 0 9.724135 0.389376 0.464451 0.229964 0.691504 1 1.114782 0.838406 0.679096 0.1851

Solution 1:

You could use one of the is_monotonic functions from algos:

In [10]: months = ['Jan', 'Feb', 'Mar', 'Apr']

In [11]: df.loc[:, months].apply(lambda x: pd.algos.is_monotonic_float64(-x)[0],
                                       axis=1)
Out[11]:
0False1True2False3True4False
dtype: bool

The is_monotonic checks whether an array it's decreasing hence the -x.values.

(This seems substantially faster than Tom's solution, even using the small DataFrame provided.)

Solution 2:

months = ['Jan', 'Feb', 'Mar', 'Apr']

Transpose so that we can use the diff method (which doesn't take an axis argument). We fill in the first row (January) with 0. Otherwise it's NaN.

In [77]: df[months].T.diff().fillna(0) <=0Out[77]: 
         01234
Jan   TrueTrueTrueTrueTrue
Feb  FalseTrueTrueTrueFalse
Mar   TrueTrueFalseTrueTrue
Apr  FalseTrueTrueTrueFalse

To check if it's monotonically decreasing, use the .all() method. By default this goes over axis 0, the rows (months).

In [78]: is_decreasing = (df[months].T.diff().fillna(0) <=0).all()

In [79]: is_decreasing
Out[79]: 
0False1True2False3True4False
dtype: bool

In [80]: df['is_decreasing'] = is_decreasing

In [81]: df
Out[81]: 
    Balance       Jan       Feb       Mar       Apr is_decreasing
09.7241350.3893760.4644510.2299640.691504False11.1147820.8384060.6790960.1851350.143883True27.6139460.9608760.2202740.7882650.606402False30.1445170.8000860.2878740.2235390.206002True41.3328380.4308120.9394020.0452620.388466False

And like you suggested, we can groupby is_decreasing and sum:

In [83]: df.groupby('is_decreasing')['Balance'].sum()
Out[83]: 
is_decreasing
False18.670919True1.259299
Name: Balance, dtype: float64

It's times like these when I love pandas.

Solution 3:

months = ['Jan', 'Feb', 'Mar', 'Apr']

df[df.loc[:, months].apply(lambda x: x.is_monotonic,axis=1)]

Note: pandas states that is_monotonic_increasing is an alias for is_monotonic so you can use either one

Solution 4:

Pandas 0.19 added a Series.is_monotonic attribute (as mentioned, the algos module was removed from Pandas public API).

As @Liam notes in his answer, is_monotonic is in fact an alias for is_monotonic_increasing, so for clarity I'd recommended directly using either is_monotonic_increasing or is_monotonic_decreasing.

Anyway, both are non-strict (i.e. is_monotonic_decreasing returns True when the sequence is either decreasing or equal), but you can combine them with is_unqiue if you need strictness.

my_df = pd.DataFrame({'A':[1,2,3],'B':[1,1,1],'C':[3,2,1]})
my_df

Out[32]: 
   A  B  C
011312122311

my_df.apply(lambda x: x.is_monotonic_increasing)  # row-wise monotonic (default axis is 0)

Out[33]: 
A     True
B     True
C    False
dtype: bool

my_df.apply(lambda x: x.is_monotonic_increasing, axis=1)  # column-wise monotonic

Out[34]: 
0True1False2False
dtype: bool

Post a Comment for "Pandas Dataframe: Check If Data Is Monotonically Decreasing"