Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count number of clusters of non-zero values in Python?

My data looks something like this:

a=[0,0,0,0,0,0,10,15,16,12,11,9,10,0,0,0,0,0,6,9,3,7,5,4,0,0,0,0,0,0,4,3,9,7,1]

Essentially, there's a bunch of zeroes before non-zero numbers and I am looking to count the number of groups of non-zero numbers separated by zeros. In the example data above, there are 3 groups of non-zero data so the code should return 3.

  • Number of zeros between groups of non-zeros is variable

Any good ways to do this in python? (Also using Pandas and Numpy to help parse the data)

like image 459
Timbo Slice Avatar asked Dec 31 '16 21:12

Timbo Slice


People also ask

How do you count the number of non-zero elements in an array in Python?

count_nonzero() function counts the number of non-zero values in the array arr. Parameters : arr : [array_like] The array for which to count non-zeros. axis : [int or tuple, optional] Axis or tuple of axes along which to count non-zeros.

How do you find the non-zero element in Python?

nonzero() function is used to Compute the indices of the elements that are non-zero. It returns a tuple of arrays, one for each dimension of arr, containing the indices of the non-zero elements in that dimension. The corresponding non-zero values in the array can be obtained with arr[nonzero(arr)] .

How do you count the number of non zeros in a NumPy array?

The Numpy count_nonzero() function is used to give the count of the nonzero elements present in the multidimensional array. With the help of this function, we can find the count of the elements in the multidimensional array which are not zero. This function has 3 parameters as arr, axis and, keepdims.

How do you count zero values in Python?

Method #1 – NumPy count_nonzero() Function This should give us the total number of zero elements. The example code above uses the arr. size property – the value from the count_nonzero function to get the number of zero elements in the array. NOTE: Python treats a false value as Zero.


3 Answers

With a as the input array, we could have a vectorized solution -

m = a!=0
out = (m[1:] > m[:-1]).sum() + m[0]

Alternatively for performance, we might use np.count_nonzero which is very efficient to count bools as is the case here, like so -

out = np.count_nonzero(m[1:] > m[:-1]) + m[0] 

Basically, we get a mask of non-zeros and count rising edges. To account for the first element that could be non-zero too and would not have any rising edge, we need to check it and add to the total sum.

Also, please note that if input a is a list, we need to use m = np.asarray(a)!=0 instead.

Sample runs for three cases -

In [92]: a  # Case1 :Given sample
Out[92]: 
array([ 0,  0,  0,  0,  0,  0, 10, 15, 16, 12, 11,  9, 10,  0,  0,  0,  0,
        0,  6,  9,  3,  7,  5,  4,  0,  0,  0,  0,  0,  0,  4,  3,  9,  7,
        1])

In [93]: m = a!=0

In [94]: (m[1:] > m[:-1]).sum() + m[0]
Out[94]: 3

In [95]: a[0] = 7  # Case2 :Add a non-zero elem/group at the start

In [96]: m = a!=0

In [97]: (m[1:] > m[:-1]).sum() + m[0]
Out[97]: 4

In [99]: a[-2:] = [0,4] # Case3 :Add a non-zero group at the end

In [100]: m = a!=0

In [101]: (m[1:] > m[:-1]).sum() + m[0]
Out[101]: 5
like image 187
Divakar Avatar answered Oct 18 '22 08:10

Divakar


You may achieve it via using itertools.groupby() with list comprehension expression as:

>>> from itertools import groupby

>>> len([is_true for is_true, _ in groupby(a, lambda x: x!=0) if is_true])
3
like image 40
Moinuddin Quadri Avatar answered Oct 18 '22 08:10

Moinuddin Quadri


simple python solution, just count changes from 0 to non-zero, by keeping track of the previous value (rising edge detection):

a=[0,0,0,0,0,0,10,15,16,12,11,9,10,0,0,0,0,0,6,9,3,7,5,4,0,0,0,0,0,0,4,3,9,7,1]

previous = 0
count = 0
for c in a:
    if previous==0 and c!=0:
        count+=1
    previous = c

print(count)  # 3
like image 45
Jean-François Fabre Avatar answered Oct 18 '22 10:10

Jean-François Fabre