Remplacer les valeurs négatives dans un tableau numpy

90

Existe-t-il un moyen simple de remplacer toutes les valeurs négatives d'un tableau par 0?

J'ai un bloc complet sur la façon de le faire en utilisant un tableau NumPy.

Par exemple

a = array([1, 2, 3, -4, 5])

J'ai besoin de revenir

[1, 2, 3, 0, 5]

a < 0 donne:

[False, False, False, True, False]

C'est là que je suis bloqué - comment utiliser ce tableau pour modifier le tableau d'origine.

bph
la source

Réponses:

137

Vous êtes à mi-chemin. Essayer:

In [4]: a[a < 0] = 0

In [5]: a
Out[5]: array([1, 2, 3, 0, 5])
NPE
la source
89

Essayez numpy.clip:

>>> import numpy
>>> a = numpy.arange(-10, 10)
>>> a
array([-10,  -9,  -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1,   0,   1,   2,
         3,   4,   5,   6,   7,   8,   9])
>>> a.clip(0, 10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Vous ne pouvez couper que la moitié inférieure avec clip(0).

>>> a = numpy.array([1, 2, 3, -4, 5])
>>> a.clip(0)
array([1, 2, 3, 0, 5])

Vous ne pouvez couper que la moitié supérieure avec clip(max=n). (C'est bien mieux que ma suggestion précédente, qui impliquait de passer NaNau premier paramètre et d'utiliser outpour forcer le type.):

>>> a.clip(max=2)
array([ 1,  2,  2, -4,  2])

Une autre approche intéressante consiste à utiliser where:

>>> numpy.where(a <= 2, a, 2)
array([ 1,  2,  2, -4,  2])

Enfin, pensez à aix de réponse. Je préfère clippour les opérations simples car c'est auto-documenté, mais sa réponse est préférable pour des opérations plus complexes.

expéditeur
la source
1
a.clip (0) suffirait puisque l'OP veut juste remplacer les valeurs négatives. a.clip (0, 10) exclurait tout ce qui est au-dessus de 10.
Usagi
1
@Hiett - Je viens de l'essayer et le clip en prendra un. Le premier est supposé min.
Usagi
doit être un problème de version avec numpy - voici ma sortie: (Pdb) np.clip (w, 0) *** TypeError: clip () prend au moins 3 arguments (2 donnés) - alors que: (Pdb) np.clip ( w, 0,1e6) array ([[0., 0.605]])
bph
1
@Hiett, de quelle version numpy? Avez-vous essayé la méthode de clip de a? La fonction intégrée numpy.clipme donne la même erreur, mais pas la méthode.
senderle
yeh si vous l'appelez de cette façon, il semble fonctionner, par exemple p w.clip (0) array ([[0., 0.605]]) - comment bizarre?
bph
10

Une autre solution Python minimaliste sans utiliser numpy:

[0 if i < 0 else i for i in a]

Pas besoin de définir des fonctions supplémentaires.

a = [1, 2, 3, -4, -5.23, 6]
[0 if i < 0 else i for i in a]

donne:

[1, 2, 3, 0, 0, 6]
Levon
la source
1
c'est bien - je me demandais quelle serait la syntaxe pour mettre l'instruction if dans la compréhension de la liste - je me suis trompé en le collant après la boucle for et en récupérant seulement deux valeurs, par exemple [0, 0] pour votre exemple list
bph
J'ai fait la même chose quand j'ai appris la compréhension des listes et que j'essayais différentes choses pour tester ma compréhension - il me semblait plus intuitif de le mettre après la boucle for pour moi aussi. Maintenant, cependant, cela fait :) Le mettre avant l' forapplique à chaque élément de la liste, le mettre après, signifie que seulement si la condition est remplie, il va dans la liste résultante.
Levon
2
@Hiett Il s'agit simplement d'utiliser l'opérateur ternaire ( i < 0 ? 0 : ien C) dans une compréhension de liste. Mettez des crochets pour le rendre plus clair [(0 if i < 0 else i) for i in a]. Mettre le if après utilise la partie filtre de la construction d'expression de liste. [(i) for i in a if i < 0]renverra uniquement une liste d'éléments inférieurs à zéro.
Paul S
2
Numpy est puissant car il effectue une grande partie du calcul par code c compilé et est donc plus rapide. En comparant cette méthode aux autres, je trouve une différence de facteur de vitesse presque 10 fois supérieure (c'est plus lent). Donc, bien qu'intuitif et facile à lire, ce n'est certainement pas pour les calculs intensifs.
rspencer le
4

Et encore une autre possibilité:

In [2]: a = array([1, 2, 3, -4, 5])

In [3]: where(a<0, 0, a)
Out[3]: array([1, 2, 3, 0, 5])
Ramon Crehuet
la source
2

Voici un moyen de le faire en Python sans NumPy. Créez une fonction qui renvoie ce que vous voulez et utilisez une compréhension de liste ou la fonction de carte .

>>> a = [1, 2, 3, -4, 5]

>>> def zero_if_negative(x):
...   if x < 0:
...     return 0
...   return x
...

>>> [zero_if_negative(x) for x in a]
[1, 2, 3, 0, 5]

>>> map(zero_if_negative, a)
[1, 2, 3, 0, 5]
Kekoa
la source
1
avait emprunté cette voie mais pensait qu'il devait y avoir un moyen plus facile, plus matlab et moins python de le faire avec numpy (car j'utilisais de toute façon des tableaux plutôt que des listes). le clip est parfait
bph