Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count the number of exact co-occurences of items in a numpy list

Tags:

python

numpy

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

like image 567
Zennie Avatar asked Oct 21 '25 04:10

Zennie


1 Answers

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
like image 119
sacuL Avatar answered Oct 22 '25 18:10

sacuL