19

I can check if the index of a pandas.DataFrame() is monotonically increasing by using is_monotonic method. However, I would like to check if one of the column value is strictly increasing in value(float/integer) ?

In [13]: my_df = pd.DataFrame([1,2,3,5,7,6,9])

In [14]: my_df
Out[14]: 
   0
0  1
1  2
2  3
3  5
4  7
5  6
6  9

In [15]: my_df.index.is_monotonic
Out[15]: True
amehta
  • 1,307
  • 3
  • 18
  • 22

5 Answers5

35

Pandas 0.19 added a public Series.is_monotonic API (previously, this was available only in the undocumented algos module).

(Updated) Note that despite its name, Series.is_monotonic only indicates whether a series is monotonically increasing (equivalent to using Series.is_monotonic_increasing). For the other way around, use Series.is_monotonic_decreasing. Anyway, both are non-strict, but you can combine them with is_unqiue to get strictness.

e.g.:

my_df = pd.DataFrame([1,2,2,3], columns = ['A'])

my_df['A'].is_monotonic    # non-strict
Out[1]: True

my_df['A'].is_monotonic_increasing    # equivalent to is_monotonic
Out[2]: True

(my_df['A'].is_monotonic_increasing and my_df['A'].is_unique)    # strict  
Out[3]: False

my_df['A'].is_monotonic_decreasing    # Other direction (also non-strict)
Out[4]: False

You can use apply to run this at a DataFrame level:

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

my_df.apply(lambda x: x.is_monotonic)
Out[33]: 
A     True
B     True
C    False
dtype: bool
OmerB
  • 4,134
  • 3
  • 20
  • 33
6

Probably the best way is to obtain a dataframe column as a numpy array without copying data around (using the .values property after column selection via indexing), and to then use a numpy-based test for checking monotonicity:

def monotonic(x):
    return np.all(np.diff(x) > 0)

monotonic(df[0].values)

A pure Python implementation, borrowed from here: Python - How to check list monotonicity

def strictly_increasing(L):
    return all(x<y for x, y in zip(L, L[1:]))
Community
  • 1
  • 1
Dr. Jan-Philip Gehrcke
  • 33,287
  • 14
  • 85
  • 130
  • i like this Python-way because it can be applied to a combination of columns too, for instance, as i had to check that pairs (read_date, read_time) in my df are sorted properly, i could simply do: strictly_increasing(list(zip(df['read_date'], df['read_time']))) – vuvu Mar 01 '19 at 16:56
2

If two indices are equal, they won't be unique. So you can just use:

my_df.Index.is_monotonic and my_df.Index.is_unique

These attributes are documented in version 15.2; is_unique is mentioned sketchily in 14.1 but just worked for me. See

http://pandas.pydata.org/pandas-docs/version/0.15.2/api.html#index http://pandas.pydata.org/pandas-docs/version/0.14.1/generated/pandas.Index.html

birone
  • 2,039
  • 6
  • 17
  • 18
0

you can just math this one:

diff = df[0] - df[0].shift(1)
is_monotonic = (diff < 0).sum() == 0 or (diff > 0).sum() == 0

all you're checking here is that either the differences are all >= 0 or all <= 0.

edit: since you only want strictly increasing, then it's just:

is_monotonic = (diff <= 0).sum() == 0
acushner
  • 9,595
  • 1
  • 34
  • 34
0

I understand that by strictly increasing you mean that the values are integers and that neighbors are separated by exactly 1? As discussed here, this is a simple method for checking named criterion:

def is_coherent(seq):
    return seq == range(seq[0], seq[-1]+1)

Using it with the first column of your my_df might look like so:

is_coherent(my_df[0].tolist())
Community
  • 1
  • 1
John
  • 74
  • 5