Reputation: 9680
I'm having a numpy ndarray where I would like to check if each row vector is monotonically increasing.
Example:
a = np.asarray([[1,2,3],[1,5,7],[4,3,6]])
monotonically_increasing(a)
Expected return:
[True, True, False]
I'm not entirely sure how to efficiently do this, since the matrices are expected to be quite large (~1000x1000), and was hoping for some help.
Upvotes: 33
Views: 30114
Reputation: 753
A function f
defined on a subset of the real numbers with real values is called monotonic if and only if it is either entirely non-increasing, or entirely non-decreasing.
is_monotonic = np.all(np.diff(a) > 0) | np.all(np.diff(a) < 0)
Upvotes: 1
Reputation: 1
There was another question related to how to handle strictly decreasing from @igorkf. I combined that answer into a useful function.
def check_monotonicity (data: np.array, increasing: bool, axis: int) -> np.array :
if increasing: # strictly increasing
return data [np.where (
np.invert (
(np.all(data[:, 1:] >= data[:, :-1], axis=axis))
) ) ]
else: # strictly decreasing
return data [np.where (
np.invert (
(np.all(data[:, 0:-1] >= data[:, 1:], axis=axis))
) ) ]
Upvotes: 0
Reputation: 1
To add to the answers provided @Jaime and all, to get the exact place where there are violations, in addition to just determining if they are strictly increasing or decreasing, I chained this as follows
a = np.array( [[1,2,3], [5,4,3], [4,5,6], [4,6,3]])
a[np.where
( np.invert
(np.all(a[:, 1:] >= a[:, :-1], axis=1))
)
]
Result:
array([[5, 4, 3],
[4, 6, 3]])
Upvotes: 0
Reputation: 23773
>>> import numpy as np
>>> a = np.asarray([[1,2,3],[1,5,7],[4,3,6]])
Find the difference between each element. np.diff
has an argument that lets you specify the axis to perform the diff
>>> np.diff(a)
array([[ 1, 1],
[ 4, 2],
[-1, 3]])
Check to see if each difference is greater than 0.
>>> np.diff(a) > 0
array([[ True, True],
[ True, True],
[False, True]], dtype=bool)
Check to see if all the differences are > 0
>>> np.all(np.diff(a) > 0)
False
>>>
As suggested by @Jaime - check that each element is greater than the element to its left:
np.all(a[:, 1:] >= a[:, :-1], axis=1)
Which appears to be about twice as fast/efficient as my diff solution.
Upvotes: 65
Reputation: 6668
You can make a function like this:
def monotonically_increasing(l):
return all(x < y for x, y in zip(l, l[1:]))
and then check for it, sublist for sublist, so
[monotonically_increasing(sublist) for sublist in a]
Upvotes: 1