205

NumPy has the efficient function/method nonzero() to identify the indices of non-zero elements in an ndarray object. What is the most efficient way to obtain the indices of the elements that do have a value of zero?

9 Answers 9

312

numpy.where() is my favorite.

>>> x = numpy.array([1,0,2,0,3,0,4,5,6,7,8])
>>> numpy.where(x == 0)[0]
array([1, 3, 5])

The method where returns a tuple of ndarrays, each corresponding to a different dimension of the input. Since the input is one-dimensional, the [0] unboxes the tuple's only element.

Sign up to request clarification or add additional context in comments.

7 Comments

I am trying to remember Python. Why does where() return a tuple? numpy.where(x == 0)[1] is out of bounds. what is the index array coupled to then?
no. where returns a tuple of ndarrays, each of them corresponding to a dimension of the input. in this case the input is an array, so the output is a 1-tuple. If x was a matrix, it would be a 2-tuple, and so on
As of numpy 1.16, the documentation for numpy.where specifically recommends using numpy.nonzero directly rather than calling where with only one argument.
@jirassimok how do you use nonzero to find zeros as the question asks?
@mLstudent33 Exactly the same way as you would use where, as seen in Dusch's answer. As per where's documentation, where(x) is equivalent to asarray(x).nonzero().
|
59

There is np.argwhere,

import numpy as np
arr = np.array([[1,2,3], [0, 1, 0], [7, 0, 2]])
np.argwhere(arr == 0)

which returns all found indices as rows:

array([[1, 0],    # Indices of the first zero
       [1, 2],    # Indices of the second zero
       [2, 1]],   # Indices of the third zero
      dtype=int64)

Comments

29

You can search for any scalar condition with:

>>> a = np.asarray([0,1,2,3,4])
>>> a == 0 # or whatver
array([ True, False, False, False, False], dtype=bool)

Which will give back the array as an boolean mask of the condition.

2 Comments

You can use this to access the zero elements: a[a==0] = epsilon
Recently found out about this notation. IMO, one of the ugliest pieces of syntactic sugar. VERY, VERY wrong, like assignment in comparison operators in C.
28

You can also use nonzero() by using it on a boolean mask of the condition, because False is also a kind of zero.

>>> x = numpy.array([1,0,2,0,3,0,4,5,6,7,8])

>>> x==0
array([False, True, False, True, False, True, False, False, False, False, False], dtype=bool)

>>> numpy.nonzero(x==0)[0]
array([1, 3, 5])

It's doing exactly the same as mtrw's way, but it is more related to the question ;)

1 Comment

This should be the accepted answer as this is the advised use of nonzero method to check conditions.
7

If you are working with a one-dimensional array there is a syntactic sugar:

>>> x = numpy.array([1,0,2,0,3,0,4,5,6,7,8])
>>> numpy.flatnonzero(x == 0)
array([1, 3, 5])

2 Comments

This works fine as long as I have only one condition. What if I want to search for "x == numpy.array(0,2,7)"? The result should be array([1,2,3,5,9]). But how can I get this?
You could do this with: numpy.flatnonzero(numpy.logical_or(numpy.logical_or(x==0, x==2), x==7))
7

You can use numpy.nonzero to find zero.

>>> import numpy as np
>>> x = np.array([1,0,2,0,3,0,0,4,0,5,0,6]).reshape(4, 3)
>>> np.nonzero(x==0)  # this is what you want
(array([0, 1, 1, 2, 2, 3]), array([1, 0, 2, 0, 2, 1]))
>>> np.nonzero(x)
(array([0, 0, 1, 2, 3, 3]), array([0, 2, 1, 1, 0, 2]))

Comments

3
import numpy as np
arr = np.arange(10000)
arr[8000:8900] = 0

%timeit np.where(arr == 0)[0]
%timeit np.argwhere(arr == 0)
%timeit np.nonzero(arr==0)[0]
%timeit np.flatnonzero(arr==0)
%timeit np.amin(np.extract(arr != 0, arr))
23.4 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
34.5 µs ± 680 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
23.2 µs ± 447 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
27 µs ± 506 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
109 µs ± 669 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Comments

2

I would do it the following way:

>>> x = np.array([[1,0,0], [0,2,0], [1,1,0]])
>>> x
array([[1, 0, 0],
       [0, 2, 0],
       [1, 1, 0]])
>>> np.nonzero(x)
(array([0, 1, 2, 2]), array([0, 1, 0, 1]))

# if you want it in coordinates
>>> x[np.nonzero(x)]
array([1, 2, 1, 1])
>>> np.transpose(np.nonzero(x))
array([[0, 0],
       [1, 1],
       [2, 0],
       [2, 1])

Comments

1
import numpy as np

x = np.array([1,0,2,3,6])
non_zero_arr = np.extract(x>0,x)

min_index = np.amin(non_zero_arr)
min_value = np.argmin(non_zero_arr)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.