Zastąp wartości ujemne w tablicy numpy

90

Czy istnieje prosty sposób na zastąpienie wszystkich wartości ujemnych w tablicy wartością 0?

Mam kompletny blok, jak to zrobić za pomocą tablicy NumPy.

Na przykład

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

Muszę wrócić

[1, 2, 3, 0, 5]

a < 0 daje:

[False, False, False, True, False]

W tym miejscu utknąłem - jak używać tej tablicy do modyfikowania oryginalnej tablicy.

bph
źródło

Odpowiedzi:

137

Jesteś w połowie drogi. Próbować:

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

In [5]: a
Out[5]: array([1, 2, 3, 0, 5])
NPE
źródło
89

Spróbuj 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])

Za pomocą można przyciąć tylko dolną połowę clip(0).

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

Możesz przyciąć tylko górną połowę za pomocą clip(max=n). (Jest to znacznie lepsze niż moja poprzednia sugestia, która obejmowała przekazanie NaNdo pierwszego parametru i użycie outdo wymuszenia typu.):

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

Innym ciekawym podejściem jest użycie where:

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

Na koniec rozważ odpowiedź aix . Wolę clipproste operacje, ponieważ dokumentuje się samoczynnie, ale jego odpowiedź jest preferowana w przypadku bardziej złożonych operacji.

nadawca
źródło
1
a.clip (0) wystarczy, ponieważ OP chce tylko zastąpić wartości ujemne. a.clip (0, 10) wykluczy wszystko powyżej 10.
Usagi
1
@Hiett - właśnie to wypróbowałem i klip zajmie jeden. Najpierw zakłada się min.
Usagi
musi być problem z wersją z numpy - heres my ouptut: (Pdb) np.clip (w, 0) *** TypeError: clip () przyjmuje co najmniej 3 argumenty (podane 2) - podczas gdy: (Pdb) np.clip ( w, 0,1e6) matrycy ([[0, 0,605]])
BPH
1
@Hiett, jaka wersja numpy? Próbowałaś klip metodę z a? Wbudowana funkcja numpy.clipdaje mi ten sam błąd, ale metoda nie.
senderle
tak, jeśli tak to nazwiesz, to wydaje się działać, np. p w.clip (0) tablica ([[0., 0.605]]) - jak dziwne?
bph
10

Kolejne minimalistyczne rozwiązanie w Pythonie bez użycia numpy:

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

Nie ma potrzeby definiowania żadnych dodatkowych funkcji.

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

plony:

[1, 2, 3, 0, 0, 6]
Levon
źródło
1
to fajnie - zastanawiałem się, jaka byłaby składnia, aby umieścić instrukcję if wewnątrz rozumienia listowego - popełniłem błąd, wklejając ją za pętlę for i dopiero wtedy odzyskałem dwie wartości, np. [0, 0] na przykład lista
bph
Zrobiłem to samo, gdy początkowo nauczyłem się rozumienia listy i próbowałem różnych rzeczy, aby sprawdzić swoje rozumienie - dla mnie również umieszczenie tego po pętli for wydawało się bardziej intuicyjne. Teraz jednak tak się dzieje :) Umieszczenie go przed znakiem powoduje forzastosowanie go do każdego elementu listy, umieszczenie go po, oznacza, że ​​tylko wtedy, gdy warunek jest spełniony, trafia do wynikowej listy.
Levon
2
@Hiett To po prostu użycie operatora trójargumentowego ( i < 0 ? 0 : iw C) wewnątrz rozumienia list. Umieść nawiasy, aby było wyraźniej [(0 if i < 0 else i) for i in a]. Wstawienie if after powoduje użycie części filtrującej konstrukcji wyrażenia listy. [(i) for i in a if i < 0]zwróci tylko listę elementów, które są mniejsze od zera.
Paul S,
2
Numpy jest potężny, ponieważ wykonuje wiele obliczeń za pomocą skompilowanego kodu c, a zatem jest szybszy. Porównując tę ​​metodę z innymi, stwierdzam prawie 10-krotną różnicę współczynnika prędkości (jest wolniejsza). Tak więc, chociaż intuicyjny i łatwy do odczytania, zdecydowanie nie jest przeznaczony dla intensywnych obliczeniowo.
rspencer,
4

I jeszcze jedna możliwość:

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
źródło
2

Oto sposób na zrobienie tego w Pythonie bez NumPy. Utwórz funkcję, która zwraca to, czego chcesz i użyj wyrażenia listowego lub funkcji mapy .

>>> 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
źródło
1
poszedł tą drogą, ale pomyślałem, że musi być łatwiejszy, mniej matlabowy, mniej Pythonowy sposób na zrobienie tego z numpy (ponieważ i tak używałem tablic zamiast list). klip jest doskonały
bph