2016-07-14 37 views
4

Nehmen wir an, ich habe ein Array von Werten, r, die irgendwo von 0 bis 1 reichen. Ich möchte alle Werte entfernen, deren Schwellenwert vom Median abweicht. Nehmen wir an, dass dieser Schwellenwert 0.5 und len(r) = 3000 ist. Dann werden alle Werte zu maskieren außerhalb dieses Bereichs, kann ich eine einfache Liste Verständnis tun, die Ich mag:Wie kann ich dieses Python-Listen-Verständnis in NumPy machen?

mask = np.array([ri < np.median(r)-0.5 or ri > np.median(r)+0.5 for ri in r])

Und wenn ich einen Timer an es:

import time 
import numpy as np 

start = time.time() 
r = np.random.random(3000) 
m = np.median(r) 
maxr,minr = m-0.5, m+0.5 
mask = [ri<minr or ri>maxr for ri in r] 
end = time.time() 
print('Took %.4f seconds'%(end-start)) 

>>> Took 0.0010 seconds

Gibt es einen schnelleren Weg, dieses Listenverständnis zu machen und die Maske mit NumPy zu erstellen?


Edit:

ich einige Vorschläge unten versucht haben, einschließlich:

  • Ein Element-weise oder Betreiber: (r<minv) | (r>maxv)

  • A Numpy logische oder: r[np.logical_or(r<minr, r>maxr)]

  • Eine absolute Differenz boolean-Array: abs(m-r) > 0.5

Und hier ist die durchschnittliche Zeit, die jeweils ein bis nach 300 Läufen nahm:

Python list comprehension: 0.6511 ms 
Elementwise or: 0.0138 ms 
Numpy logical or: 0.0241 ms 
Absolute difference: 0.0248 ms 

Wie Sie sehen können, das element Oder war immer die schnellste, um fast einen Faktor von zwei (weiß nicht, wie das mit Array-Elementen skalieren würde). Wer wusste.

+0

'[ri <-maxr' ist die minus einen Tippfehler melden Sie sich hier? – ayhan

+0

@ayhan yea Sorry, auch die Min und Max wurden gefloppt – Anonymous

+1

Versuchen Sie '(r> maxr) | (r ayhan

Antwort

3

Sie können numpige bedingte Auswahlen verwenden, um ein neues Array ohne diese Werte zu erstellen.

start = time.time() 
m = np.median(r) 
maxr,minr = m-0.5, m+0.5 
filtered_array = r[ (r < minr) | (r > maxr) ] 
end = time.time() 
print('Took %.4f seconds'%(end-start)) 

filtered_array ist Scheibe r ohne maskierten Werte (alle Werte, die später durch die Maske bereits in filtered_array entfernt werden entfernt).

Update: verwendete kürzere Syntax von @ayhan vorgeschlagen.

+0

Das ist am schnellsten, danke. Obwohl Ihre ursprüngliche Antwort mit 'np.logical_or()' langsamer war. – Anonymous

3

One-Liner ...

new_mask = abs(np.median(r) - r) > 0.5 
+0

Schön und prägnant, aber nicht am schnellsten, siehe meine Bearbeitung. – Anonymous

+0

Sehr nützlich, wenn die Enden der Verteilungen benötigt werden. Ich mag Klarheit. –