I am trying to figure out the fastest way to count how many time two values are located one after the other in a numpy list.
For example:
list = [1, 5, 4, 1, 2, 4, 6, 7, 2, 1, 3, 3, 1, 2]
and I want to count the number of times the value 1
follows the value 2
(but not vice versa)
In the example above, the answer should be 1
since 1
follows 2
only once.
I can obviously reach the answer with a simple for-loop that adds to a counter every time the item i
is equal 1
and item i-1
equals 2
, but I feel that there must be a faster way to do it,
Thanks
You coud do this using np.diff
and np.where
:
import numpy as np
mylist = [1, 5, 4, 1, 2, 4, 6, 7, 2, 1, 3, 3, 1, 2]
# Turn your list into a numpy array
myarray = np.array(mylist)
# find occurences where myarray is 2 and the following element is 2 minus 1
np.sum((myarray[:-1] == 2) & (np.diff(myarray) == -1))
Which returns 1
Timings on a large array:
On a small list, the time difference between an iterative method and numpy
methods will not be noticeable. But on a large array, as in the example below, the performance of numpy
is much better.
import timeit
mylist = np.random.choice(range(0,9), 1000000)
def np_method(mylist = mylist):
return np.sum((mylist[:-1] == 2) & (np.diff(mylist) == -1))
def zip_loop(a = mylist):
return len( [1 for i,j in zip(a, a[1:]) if i == 2 and j == 1] )
def for_loop(list1 = mylist):
count=0
desired_num=2
follower_num=1
for i in range(len(list1)-1):
if list1[i]==desired_num:
if list1[i+1]==follower_num:
count+=1
return count
>>> timeit.timeit(np_method, number = 100) / 100
0.006748438189970329
>>> timeit.timeit(zip_loop, number = 100) / 100
0.3811768989200209
>>> timeit.timeit(for_loop, number = 100) / 100
0.3774999916599336
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With