Reputation: 470
Is there a way to search a Numpy array for consecutive values and return their index?
For example, if we use argmax on an array to find the first instance of a single element:
import numpy as np
a = np.array((0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1))
print(np.argmax(a == 1))
We get the result:
3
Is there a way to search this same array for the first instance of a pair? E.g. I want to get the value 6
for the following code:
import numpy as np
a = np.array((0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1))
print(np.argmax(a == [1, 1]))
But instead it returns:
0
Upvotes: 1
Views: 179
Reputation: 221554
For small number of consecutive search pattern, we can simply slice and look for all matches and finally use our-favourite argmax
.
Hence, for 2
consecutive search pattern, it would be -
In [6]: ((a[:-1]==1) & (a[1:]==1)).argmax()
Out[6]: 6
Some explanation
It's all about slicing, as we get two one-offsetted array slices. The one-offset comes because of the window-length of consecutive search being 2
. So, for a search window-length of 3
, we need to consider two-offsetted array slices and so on. Now, back to our simplistic two-consecutive window case, we have one-offsetted slices. We compare these against 1
, which gives us boolean arrays of matches. Then comes AND-ing
, so that the entire window is covered. Finally jumps in our argmax
to get the start of the first of those islands!
A break-down of the steps should help clarify further on the given sample -
In [24]: a
Out[24]: array([0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1])
In [25]: a[:-1]
Out[25]: array([0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1])
In [26]: a[:-1]==1
Out[26]:
array([False, False, False, True, False, False, True, True, False,
True, True])
In [27]: a[1:]==1
Out[27]:
array([False, False, True, False, False, True, True, False, True,
True, True])
In [28]: (a[:-1]==1) & (a[1:]==1)
Out[28]:
array([False, False, False, False, False, False, True, False, False,
True, True])
In [29]: ((a[:-1]==1) & (a[1:]==1)).argmax()
Out[29]: 6
For larger number of cons. occurrences, we can resort to something more built-in and use np.convolve
, like so -
In [20]: W = 2 # window-length
In [21]: np.convolve(a,[1]*W,'same').argmax()-W//2
Out[21]: 6
In [22]: W = 3
In [23]: np.convolve(a,[1]*W,'same').argmax()-W//2
Out[23]: 9
Upvotes: 1