2010-08-02 2 views
31

Wenn ich habe ein Array wieWie werden negative Elemente ohne eine Schleife in null umgewandelt?

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

ich alle negativen Elemente auf Null gesetzt werden soll: [2, 3, 0, 0, 3]. Wie macht man es mit numpy ohne eine explizite for? Ich brauche die modifizierte a in einer Berechnung verwendet werden, beispielsweise

c = a * b 

wo b ist ein weiteres Array mit der gleichen Länge der ursprünglichen a

Schlussfolgerung

import numpy as np 
from time import time 

a = np.random.uniform(-1, 1, 20000000) 
t = time(); b = np.where(a>0, a, 0); print "1. ", time() - t 
a = np.random.uniform(-1, 1, 20000000) 
t = time(); b = a.clip(min=0); print "2. ", time() - t 
a = np.random.uniform(-1, 1, 20000000) 
t = time(); a[a < 0] = 0; print "3. ", time() - t 
a = np.random.uniform(-1, 1, 20000000) 
t = time(); a[np.where(a<0)] = 0; print "4. ", time() - t 
a = np.random.uniform(-1, 1, 20000000) 
t = time(); b = [max(x, 0) for x in a]; print "5. ", time() - t 
  1. 1,38629984856
  2. 0,516846179962 < - schneller a.clip (min = 0);
  3. 0,615426063538
  4. 0,944557905197
  5. 51,7364809513
+1

Auf meinem Rechner ist 'a [a <0] = 0 'wesentlich schneller als' a.clip (min = 0) '. – user545424

Antwort

54
a = a.clip(min=0) 
+0

bessere Lösung? –

+0

Es könnte sein. Sie müssen sie testen, um festzustellen, welche die schnellste ist. Ich benutze nicht viel, daher bin ich mir nicht sicher, obwohl numpy sehr gut optimiert sein sollte, also könnte es meine Antworten deutlich übertreffen. –

+1

wiso, ich denke du hast den schnellsten Weg gefunden. '% Zeit a.clip (min = 0, out = a)' nahm 5,65 Mikrosekunden pro Schleife. '% Zeit np.wobei (a> 0, a, 0)' 24 Mikrosekunden pro Schleife benötigte, '% Zeit a [a <0] = 0 'benötigte 11,6 Mikrosekunden pro Schleife. – unutbu

12

Ich würde dies tun:

a[a < 0] = 0 

Wenn Sie das Original a behalten wollen und setzen nur die negativen Elemente auf Null eine Kopie, Sie können das Array zuerst kopieren:

c = a.copy() 
c[c < 0] = 0 
+0

Es funktioniert nicht mit mehreren Dimensionen. – Dmitry

3

Verwenden where

a[numpy.where(a<0)] = 0 
5

Ein weiterer Trick ist die Multiplikation zu verwenden. Dies scheint tatsächlich viel schneller als jede andere Methode hier zu sein. Zum Beispiel

b = a*(a>0) # copies data 

oder

a *= (a>0) # in-place zero-ing 

lief ich Tests mit timeit, und die die < Vorausberechnen> weil einige von ihnen an Ort und Stelle zu ändern, und das würde stark Ergebnisse bewirken. In allen Fällen war anp.random.uniform(-1, 1, 20000000), aber mit negativen bereits auf 0 gesetzt, aber L = a < 0 und G = a > 0 vor a wurde geändert. Die clip ist relativ negativ betroffen, da sie L oder G nicht zu verwenden (aber die Berechnung auf derselben Maschine dauerte nur jeweils 17ms, so ist es nicht die Hauptursache der Geschwindigkeitsdifferenz).

%timeit b = np.where(G, a, 0) # 132ms copies 
%timeit b = a.clip(min=0)  # 165ms copies 
%timeit a[L] = 0    # 158ms in-place 
%timeit a[np.where(L)] = 0  # 122ms in-place 
%timeit b = a*G    # 87.4ms copies 
%timeit np.multiply(a,G,a)  # 40.1ms in-place (normal code would use `a*=G`) 

Bei der Auswahl des in-Place-Verfahren statt clip zu bestrafen, die folgenden Timings kommen:

%timeit b = np.where(a>0, a, 0)    # 152ms 
%timeit b = a.clip(min=0)     # 165ms 
%timeit b = a.copy(); b[a<0] = 0   # 231ms 
%timeit b = a.copy(); b[np.where(a<0)] = 0 # 205ms 
%timeit b = a*(a>0)       # 108ms 
%timeit b = a.copy(); b*=a>0    # 121ms 

Nicht in-place Verfahren von 20ms nicht benachteiligt werden (die Zeit, die benötigt a>0 zu berechnen oder a<0) und die In-Place-Methoden bestrafen 73-83 ms (so dauert es etwa 53-63ms, b.copy() zu tun).

Insgesamt sind die Multiplikationsmethoden viel schneller als clip. Wenn nicht an Ort und Stelle, ist es schneller 1.5x. Wenn Sie es an Ort und Stelle tun können, dann ist es 2.75x schneller.

+0

So verwenden Sie vorberechnete Mengen bedeutet Betrug –

+0

Aber sie alle (aber eins) verwenden vorberechnete Werte. Und die Berechnungen, die vorberechnet wurden, sind schnell und dauern unter derselben Bedingung 17 ms auf der gleichen Maschine, so dass sie nicht die Ursache der Geschwindigkeitsdifferenz sind. Und wenn ich sie nicht vorberechnen würde, dann würden die In-Place-Methoden viel schneller aussehen, da es nach dem ersten Versuch nichts mehr geben würde, was null wäre. – coderforlife

+0

Lassen Sie mich einen fairen Vergleich zeigen –