Pandas Dataframe: Check If Data Is Monotonically Decreasing
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"