Efficiently check if numpy ndarray values are strictly increasing
Question:
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 (~1000×1000), and was hoping for some help.
Answers:
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]
>>> 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.
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]])
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))
) ) ]
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 (~1000×1000), and was hoping for some help.
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]
>>> 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.
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]])
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))
) ) ]