Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting indices of both zero and nonzero elements in array

Tags:

python

numpy

I need to find the indicies of both the zero and nonzero elements of an array.

Put another way, I want to find the complementary indices from numpy.nonzero().

The way that I know to do this is as follows:

indices_zero = numpy.nonzero(array == 0)
indices_nonzero = numpy.nonzero(array != 0)

This however means searching the array twice, which for large arrays is not efficient. Is there an efficient way to do this using numpy?

like image 681
amicitas Avatar asked Nov 28 '12 06:11

amicitas


People also ask

How do you find the indices of a nonzero element?

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 nonzero elements in an array?

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 index of a non zero element in Matlab?

k = find( X , n ) returns the first n indices corresponding to the nonzero elements in X . k = find( X , n , direction ) , where direction is 'last' , finds the last n indices corresponding to nonzero elements in X .

Are NP arrays zero indexed?

You can access an array element by referring to its index number. The indexes in NumPy arrays start with 0, meaning that the first element has index 0, and the second has index 1 etc.


3 Answers

Assuming you already have the range for use numpy.arange(len(array)), just get and store the logical indices:

bindices_zero = (array == 0)

then when you actually need the integer indices you can do

indices_zero = numpy.arange(len(array))[bindices_zero]

or

indices_nonzero = numpy.arange(len(array))[~bindices_zero]
like image 146
Dr. Andrew Avatar answered Sep 23 '22 13:09

Dr. Andrew


You can use boolean indexing:

In [82]: a = np.random.randint(-5, 5, 100)

In [83]: a
Out[83]: 
array([-2, -1,  4, -3,  1, -2,  2, -1,  2, -1, -3,  3, -3, -4,  1,  2,  1,
        3,  3,  0,  1, -3, -4,  3, -5, -1,  3,  2,  3,  0, -5,  4,  3, -5,
       -3,  1, -1,  0, -4,  0,  1, -5, -5, -1,  3, -2, -5, -5,  1,  0, -1,
        1,  1, -1, -2, -2,  1,  1, -4, -4,  1, -3, -3, -5,  3,  0, -5, -2,
       -2,  4,  1, -4, -5, -1,  3, -3,  2,  4, -4,  4,  2, -2, -4,  3,  4,
       -2, -4,  2, -4, -1,  0, -3, -1,  2,  3,  1,  1,  2,  1,  4])

In [84]: mask = a != 0

In [85]: a[mask]
Out[85]: 
array([-2, -1,  4, -3,  1, -2,  2, -1,  2, -1, -3,  3, -3, -4,  1,  2,  1,
        3,  3,  1, -3, -4,  3, -5, -1,  3,  2,  3, -5,  4,  3, -5, -3,  1,
       -1, -4,  1, -5, -5, -1,  3, -2, -5, -5,  1, -1,  1,  1, -1, -2, -2,
        1,  1, -4, -4,  1, -3, -3, -5,  3, -5, -2, -2,  4,  1, -4, -5, -1,
        3, -3,  2,  4, -4,  4,  2, -2, -4,  3,  4, -2, -4,  2, -4, -1, -3,
       -1,  2,  3,  1,  1,  2,  1,  4])

In [86]: a[-mask]
Out[86]: array([0, 0, 0, 0, 0, 0, 0])
like image 34
bmu Avatar answered Sep 23 '22 13:09

bmu


I'm not sure about a built-in numpy method for accomplishing this, but you could use an old-fashioned for loop, I believe. Something like:

indices_zero = []
indices_nonzero = []

for index in xrange(len(array)):
    if array[index] == 0:
        indicies_zero.append(index)
    else:
        indicies_nonzero.append(index)

Something like this should accomplish what you want, by only looping once.

like image 24
mjgpy3 Avatar answered Sep 22 '22 13:09

mjgpy3