2012-10-21 10 views
31

devo contare tutti i valori in una matrice (2-d array) che sono superiori 200.contare tutti i valori in una matrice superiore ad un valore

Il codice che annotato per questo è:

za=0 
p31 = numpy.asarray(o31) 
for i in range(o31.size[0]): 
    for j in range(o32.size[1]): 
     if p31[i,j]<200: 
      za=za+1 
print za 

o31 è un'immagine e la sto convertendo in una matrice per poi trovare i valori.

La mia domanda è, c'è un modo più semplice per farlo?

+1

Questo non stampa semplicemente il numero di valori inferiori a 200 e non i valori effettivi? –

+0

Sì. Ho solo bisogno del totale di tutti i valori invece dei valori effettivi stessi. –

+0

Anche qui non ottieni il totale. Imposta 'za' in una lista vuota' za = [] ', quindi' za.append (p31 [i, j]) ', infine fuori dal ciclo for,' print sum (za) '; ma sono sicuro che c'è un modo migliore dal momento che stai usando Numpy. –

risposta

45

La funzione numpy.where è un tuo amico. Poiché è implementato per sfruttare appieno il tipo di dati dell'array, per immagini di grandi dimensioni si dovrebbe notare un miglioramento della velocità rispetto alla soluzione Python pura fornita.

Utilizzando numpy.where direttamente produrrà una maschera booleano che indica se certi valori corrispondono ai suoi condizioni:

>>> data 
array([[1, 8], 
     [3, 4]]) 
>>> numpy.where(data > 3) 
(array([0, 1]), array([1, 1])) 

e la maschera può essere utilizzato per indicizzare la matrice direttamente per ottenere i valori effettivi:

>>> data[ numpy.where(data > 3) ] 
array([8, 4]) 

Esattamente dove si prende da lì dipenderà da quale forma vuoi i risultati in.

+6

Grazie ... Ma ho bisogno del numero totale di valori, non del valori stessi .. dovrei fare sum (numpy.where (dati <200))? –

+0

Se si desidera il numero di valori OF, non la somma, si farebbe len (numpy.where (dati <200)) – jimh

+0

se la condizione è cambiata a> 0, quindi ritornerà (array ([0, 0, 1, 1 ]), array ([0, 1, 0, 1])), cosa significa? o è un bug? – hihell

15

ci sono molti modi per raggiungere questo, come f latten-filtro o semplicemente enumerare, ma penso che usando Boolean/mask array è la più semplice (e IIRC un molto più veloce uno):

>>> y = np.array([[123,24123,32432], [234,24,23]]) 
array([[ 123, 24123, 32432], 
     [ 234, 24, 23]]) 
>>> b = y > 200 
>>> b 
array([[False, True, True], 
     [ True, False, False]], dtype=bool) 
>>> y[b] 
array([24123, 32432, 234]) 
>>> len(y[b]) 
3 
>>>> y[b].sum() 
56789 

Aggiornamento:

Come nneonneo ha risposto, se tutto quello che vuoi è il numero di elementi che supera la soglia, puoi semplicemente fare:

>>>> (y>200).sum() 
3 

che è una soluzione più semplice.


confronto Connessione con filter:

### use boolean/mask array ### 

b = y > 200 

%timeit y[b] 
100000 loops, best of 3: 3.31 us per loop 

%timeit y[y>200] 
100000 loops, best of 3: 7.57 us per loop 

### use filter ### 

x = y.ravel() 
%timeit filter(lambda x:x>200, x) 
100000 loops, best of 3: 9.33 us per loop 

%timeit np.array(filter(lambda x:x>200, x)) 
10000 loops, best of 3: 21.7 us per loop 

%timeit filter(lambda x:x>200, y.ravel()) 
100000 loops, best of 3: 11.2 us per loop 

%timeit np.array(filter(lambda x:x>200, y.ravel())) 
10000 loops, best of 3: 22.9 us per loop 

*** use numpy.where *** 

nb = np.where(y>200) 
%timeit y[nb] 
100000 loops, best of 3: 2.42 us per loop 

%timeit y[np.where(y>200)] 
100000 loops, best of 3: 10.3 us per loop 
+0

'timeit y [b]' omette metà del codice dal calcolo fatto nel filtro. '% timeit y [y> 200]' è equivalente-ish. –

44

Questo è molto semplice, con matrici booleane:

p31 = numpy.asarray(o31) 
za = (p31 < 200).sum() # p31<200 is a boolean array, so `sum` counts the number of True elements 
6

Ecco una variante che usa indicizzazione fantasia e ha i valori reali come intermedio:

p31 = numpy.asarray(o31) 
values = p31[p31<200] 
za = len(values) 
+0

Questa è solo l'indicizzazione booleana regolare. –

Problemi correlati