167

We initialize a numpy array with zeros as bellow:

np.zeros((N,N+1))

But how do we check whether all elements in a given n*n numpy array matrix is zero.
The method just need to return a True if all the values are indeed zero.

8 Answers 8

254

The other answers posted here will work, but the clearest and most efficient function to use is numpy.any():

>>> all_zeros = not np.any(a)

or

>>> all_zeros = not a.any()
  • This is preferred over numpy.all(a==0) because it uses less RAM. (It does not require the temporary array created by the a==0 term.)
  • Also, it is faster than numpy.count_nonzero(a) because it can return immediately when the first nonzero element has been found.
    • Edit: As @Rachel pointed out in the comments, np.any() no longer uses "short-circuit" logic, so you won't see a speed benefit for small arrays.
Sign up to request clarification or add additional context in comments.

2 Comments

As of a minute ago, numpy's any and all do not short-circuit. I believe they are sugar for logical_or.reduce and logical_and.reduce. Compare to each other and my short-circuiting is_in: all_false = np.zeros(10**8) all_true = np.ones(10**8) %timeit np.any(all_false) 91.5 ms ± 1.82 ms per loop %timeit np.any(all_true) 93.7 ms ± 6.16 ms per loop %timeit is_in(1, all_true) 293 ns ± 1.65 ns per loop
That's a great point, thanks. It looks like short-circuiting used to be the behavior, but that was lost at some point. There is some interesting discussion in the answers to this question.
95

Check out numpy.count_nonzero.

>>> np.count_nonzero(np.eye(4))
4
>>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]])
5

2 Comments

You'd want not np.count_nonzero(np.eye(4)) to return True only if all the values are 0.
array.nonzero()[0].size == 0 tends to be faster in practice
77

I'd use np.all here, if you have an array a:

>>> np.all(a==0)

2 Comments

I like that this answer checks for non zero values as well. For example, one can check whether all elements in an array are the same by doing np.all(a==a[0]). Thanks a lot!
This solution is also a little more efficient than np.count_nonzero. %timeit num_of_non_zeros = np.count_nonzero(zeros_vector) 18.2 µs ± 386 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) %timeit num_of_non_zeros = np.all((zeros_vector == 0)) 7.31 µs ± 41.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
17

As another answer says, you can take advantage of truthy/falsy evaluations if you know that 0 is the only falsy element possibly in your array. All elements in an array are falsy iff there are not any truthy elements in it.*

>>> a = np.zeros(10)
>>> not np.any(a)
True

However, the answer claimed that any was faster than other options due partly to short-circuiting. As of 2018, Numpy's all and any do not short-circuit.

If you do this kind of thing often, it's very easy to make your own short-circuiting versions using numba:

import numba as nb

# short-circuiting replacement for np.any()
@nb.jit(nopython=True)
def sc_any(array):
    for x in array.flat:
        if x:
            return True
    return False

# short-circuiting replacement for np.all()
@nb.jit(nopython=True)
def sc_all(array):
    for x in array.flat:
        if not x:
            return False
    return True

These tend to be faster than Numpy's versions even when not short-circuiting. count_nonzero is the slowest.

Some input to check performance:

import numpy as np

n = 10**8
middle = n//2
all_0 = np.zeros(n, dtype=int)
all_1 = np.ones(n, dtype=int)
mid_0 = np.ones(n, dtype=int)
mid_1 = np.zeros(n, dtype=int)
np.put(mid_0, middle, 0)
np.put(mid_1, middle, 1)
# mid_0 = [1 1 1 ... 1 0 1 ... 1 1 1]
# mid_1 = [0 0 0 ... 0 1 0 ... 0 0 0]

Check:

## count_nonzero
%timeit np.count_nonzero(all_0) 
# 220 ms ± 8.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.count_nonzero(all_1)
# 150 ms ± 4.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

### all
# np.all
%timeit np.all(all_1)
%timeit np.all(mid_0)
%timeit np.all(all_0)
# 56.8 ms ± 3.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 57.4 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 55.9 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# sc_all
%timeit sc_all(all_1)
%timeit sc_all(mid_0)
%timeit sc_all(all_0)
# 44.4 ms ± 2.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 22.7 ms ± 599 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 288 ns ± 6.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

### any
# np.any
%timeit np.any(all_0)
%timeit np.any(mid_1)
%timeit np.any(all_1)
# 60.7 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 60 ms ± 287 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 57.7 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# sc_any
%timeit sc_any(all_0)
%timeit sc_any(mid_1)
%timeit sc_any(all_1)
# 41.7 ms ± 1.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 22.4 ms ± 1.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 287 ns ± 12.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

* Helpful all and any equivalences:

np.all(a) == np.logical_not(np.any(np.logical_not(a)))
np.any(a) == np.logical_not(np.all(np.logical_not(a)))
not np.all(a) == np.any(np.logical_not(a))
not np.any(a) == np.all(np.logical_not(a))

Comments

2

This will work.

def check(arr):
    if np.all(arr == 0):
        return True
    return False

1 Comment

you could just do return np.all(arr == 0)
2

If all elements in ur array are larger or equal than 0. I think use sum is the fastest way.

test = np.ones((128, 128, 128))
%%timeit
not np.any(test)
>>> 1.46 ms ± 9.09 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
np.sum(test) == 0
>>> 646 µs ± 3.19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Comments

1

If you want to classify 1e-15's as zero:

def all_zero( numpy_array ):
    return np.allclose( numpy_array, np.zeros_like(numpy_array) )

Comments

-11

If you're testing for all zeros to avoid a warning on another numpy function then wrapping the line in a try, except block will save having to do the test for zeros before the operation you're interested in i.e.

try: # removes output noise for empty slice 
    mean = np.mean(array)
except:
    mean = 0

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.