2011-08-23 16 views
22

Ho una matrice. I valori validi non sono zero (positivo o negativo). Voglio trovare il minimo e il massimo all'interno dell'array che non dovrebbe tenere conto degli zeri. Ad esempio se i numeri sono solo negativi. Gli zeri saranno problematici.Trova gli zeri min/max esclusi in una matrice numpy (o una tupla) in python

+2

Qual è la tua domanda? Che cosa hai provato? Come non ha funzionato? –

risposta

43

ne dite:

import numpy as np 
minval = np.min(a[np.nonzero(a)]) 
maxval = np.max(a[np.nonzero(a)]) 

dove a è l'array.

+1

+1 per usare numpy – rubik

+1

+1 ci vorranno anche alcuni minuti per accettare la risposta – Shan

+0

@ Shan: Usare gli array mascherati può evitare la copia creata da 'a [np.nonzero (a)]' - guarda la mia risposta. –

0

Un modo semplice sarebbe utilizzare una comprensione di lista per escludere gli zeri.

>>> tup = (0, 1, 2, 5, 2) 
>>> min([x for x in tup if x !=0]) 
1 
+0

L'OP sta cercando una soluzione per gli array di numpy, non per le tuple di pitone. Come nell'altro commento, non avrò downvote, ma questo non è rilevante per gli array numpy. – JoshAdel

+0

Il titolo della domanda dice "in una matrice numpy (o una tupla)". – Wilduck

+0

non ha visto la tupla nel titolo e legge solo la domanda che dice array. Sono corretto +1. Ho saltato su di te (e l'altra risposta), perché le persone pubblicano soluzioni a domande paralizzanti trattandole come se fossero elenchi di numpy, che non sono. È un vero peccato personale, dal momento che la soluzione numpy è spesso selvaggiamente più efficiente. – JoshAdel

0

È possibile utilizzare un generatore di espressione per filtrare gli zeri:

array = [-2, 0, -4, 0, -3, -2] 
max(x for x in array if x != 0) 
+1

Penso che l'OP stia parlando di array numpy e non di liste python. C'è una differenza, anche se la tua soluzione è corretta per il futuro. Non andando a downvote, ma solo per quello che sai. – JoshAdel

+0

Ah, ho appena visto l'array, non ho visto il tag numpy. –

15

Se è possibile scegliere il valore "non valido" nella propria matrice, è meglio utilizzare nan invece di 0:

>>> a = numpy.array([1.0, numpy.nan, 2.0]) 
>>> numpy.nanmax(a) 
2.0 
>>> numpy.nanmin(a) 
1.0 

Se questo non è possibile, si può usare una maschera di matrice:

>>> a = numpy.array([1.0, 0.0, 2.0]) 
>>> ma = numpy.ma.masked_equal(a, 0.0, copy=False) 
>>> ma.max() 
2.0 
>>> ma.min() 
1.0 

Rispetto a Josh's answer using advanced indexing, questo ha il vantaggio di evitare di creare una copia dell'array.

+0

cos'è questo ma ... non è un'altra copia? – Shan

+0

+1 Gli array mascherati sono un'altra soluzione piacevole (e spesso inutilizzata) – JoshAdel

+2

@Sven: quando faccio 'ma.base is a' ottengo false, quindi non sembra che' ma' sia solo una vista di 'a 'e c'è una copia della memoria da qualche parte. O sto provando questo nel modo sbagliato? – JoshAdel

2

Ecco un altro modo di mascherare che penso sia più facile da ricordare (anche se copia l'array). Per il caso in questione, va in questo modo:

>>> import numpy 
>>> a = numpy.array([1.0, 0.0, 2.0]) 
>>> ma = a[a != 0] 
>>> ma.max() 
2.0 
>>> ma.min() 
1.0 
>>> 

Si generalizza ad altre espressioni come a> 0, numpy.isnan (a), ... E si può combinare maschere con operatori standard (+ significa OR, * significa AND, - significa NOT) ad esempio:

# Identify elements that are outside interpolation domain or NaN 
outside = (xi < x[0]) + (eta < y[0]) + (xi > x[-1]) + (eta > y[-1]) 
outside += numpy.isnan(xi) + numpy.isnan(eta) 
inside = -outside 
xi = xi[inside] 
eta = eta[inside] 
Problemi correlati