Risposte:
Dai un'occhiata a numpy.count_nonzero .
>>> np.count_nonzero(np.eye(4))
4
>>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]])
5
Le altre risposte pubblicate qui funzioneranno, ma la funzione più chiara ed efficiente da utilizzare è numpy.any()
:
>>> all_zeros = not np.any(a)
o
>>> all_zeros = not a.any()
numpy.all(a==0)
perché utilizza meno RAM. (Non richiede l'array temporaneo creato dal a==0
termine.)numpy.count_nonzero(a)
perché può tornare immediatamente quando è stato trovato il primo elemento diverso da zero.np.any()
non usa più la logica "cortocircuito", quindi non vedrai un vantaggio in termini di velocità per i piccoli array.any
e nonall
vanno in cortocircuito. Credo che siano zucchero per e . Confronta tra loro e il mio cortocircuito : logical_or.reduce
logical_and.reduce
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
Userei np.all qui, se hai un array a:
>>> np.all(a==0)
np.all(a==a[0])
. Molte grazie!
Come dice un'altra risposta, puoi trarre vantaggio da valutazioni veritiere / false se sai che 0
è l'unico elemento falso possibilmente nel tuo array. Tutti gli elementi in un array sono falsi se e solo se non ci sono elementi veritieri in esso. *
>>> a = np.zeros(10)
>>> not np.any(a)
True
Tuttavia, la risposta affermava che any
era più veloce di altre opzioni a causa in parte del cortocircuito. A partire dal 2018, Numpy all
e any
non cortocircuitano .
Se fai spesso questo genere di cose, è molto facile creare le tue versioni in cortocircuito usando 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
Questi tendono ad essere più veloci delle versioni di Numpy anche quando non sono in cortocircuito. count_nonzero
è il più lento.
Alcuni input per controllare le prestazioni:
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]
Dai un'occhiata:
## 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)
* Utile all
ed any
equivalenze:
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))
Se stai testando tutti gli zeri per evitare un avviso su un'altra funzione numpy, avvolgere la linea in una prova, tranne il blocco salverà dover fare il test per gli zeri prima dell'operazione a cui sei interessato, ad es.
try: # removes output noise for empty slice
mean = np.mean(array)
except:
mean = 0
not np.count_nonzero(np.eye(4))
restituireTrue
solo se tutti i valori sono 0.