67 votes

Trouver le min/max en excluant les zéros dans un tableau numpy (ou un tuple) en python

J'ai un tableau. Les valeurs valides sont différentes de zéro (positives ou négatives). Je veux trouver le minimum et le maximum dans le tableau qui ne doit pas prendre en compte les zéros. Par exemple, si les nombres sont uniquement négatifs. Les zéros seront problématiques.

4 votes

Quelle est votre question ? Qu'avez-vous essayé ? Comment cela n'a-t-il pas fonctionné ?

116voto

JoshAdel Points 15911

Pourquoi pas :

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

a est votre tableau.

3 votes

@Shan : L'utilisation de tableaux masqués permet d'éviter la copie créée par a[np.nonzero(a)] -- voir ma réponse.

36voto

Sven Marnach Points 133943

Si vous pouvez choisir la valeur "invalide" dans votre tableau, il est préférable d'utiliser nan au lieu de 0 :

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

Si cela n'est pas possible, vous pouvez utiliser un masque de tableau :

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

Par rapport à Réponse de Josh utilisant l'indexation avancée Cette méthode a l'avantage d'éviter de créer une copie du tableau.

0 votes

Qu'est-ce que ce ma... n'est-ce pas une autre copie ?

0 votes

+1 Les tableaux masqués sont une autre solution intéressante (et souvent sous-utilisée).

2 votes

@Sven : quand je le ferai ma.base is a J'obtiens faux, de sorte que cela ne ressemble pas à ma n'est qu'une vue de a et qu'il existe une copie de la mémoire quelque part. Ou est-ce que je teste cela de la mauvaise manière ?

7voto

uniomni Points 171

Voici une autre façon de masquer qui, je pense, est plus facile à retenir (bien qu'elle copie le tableau). Pour le cas qui nous occupe, cela se passe comme suit :

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

Elle se généralise à d'autres expressions telles que a > 0, numpy.isnan(a), ... Et vous pouvez combiner les masques avec les opérateurs standard (+ signifie OR, * signifie AND, - signifie NOT), par ex :

# 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]

4voto

Ehsan Points 10771

Réseaux masqués en général sont conçus exactement pour ce genre d'objectifs. Vous pouvez exploiter le masquage des zéros d'un tableau (ou N'IMPORTE QUEL tout autre type de masque que vous désirez, même les masques qui sont plus compliqués qu'une simple égalité) et faire la plupart des choses que vous faites sur des tableaux normaux sur votre tableau masqué. Vous pouvez également spécifier un axe pour lequel vous souhaitez trouver le minimum :

import numpy.ma as ma
mx = ma.masked_array(x, mask=x==0)
mx.min()

Exemple d'entrée :

x = np.array([1.0, 0.0, 2.0])

sortie :

1.0

4voto

Chris Pickett Points 958

Vous pourriez utiliser une expression de générateur pour filtrer les zéros :

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

1 votes

Je pense que l'OP parle de tableaux numpy et non de listes python. Il y a une différence, bien que votre solution soit correcte pour les listes. Je ne vais pas vous décoter, mais juste pour que vous le sachiez.

0 votes

Ahh, je viens de voir array, je n'ai pas vu le tag numpy.

1 votes

Cela fonctionne toujours sur les tableaux numpy, donc c'est une réponse valide. Pour les petits tableaux comme celui-ci, elle est également beaucoup plus rapide que la version numpy.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X