Numpy ile bir dizinin verimli eşikleme filtresi


81

Belirli bir eşikten düşük olan öğeleri kaldırmak için bir diziyi filtrelemem gerekiyor. Şu anki kodum şöyle:

threshold = 5
a = numpy.array(range(10)) # testing data
b = numpy.array(filter(lambda x: x >= threshold, a))

Sorun, bunun lambda işlevli (yavaş) bir filtre kullanarak geçici bir liste oluşturmasıdır.

Bu oldukça basit bir işlem olduğu için, belki bunu verimli bir şekilde yapan bir uyuşukluk işlevi vardır, ancak ben bulamadım.

Bunu başarmanın başka bir yolunun diziyi sıralamak, eşiğin indeksini bulmak ve bu indeksten sonra bir dilim döndürmek olabileceğini düşündüm, ancak bu küçük girdiler için daha hızlı olsa bile (ve yine de fark edilmeyecek) ), girdi boyutu büyüdükçe kesinlikle asimptotik olarak daha az verimlidir.

Herhangi bir fikir? Teşekkürler!

Güncelleme : Ben de bazı ölçümler yaptım ve sıralama + dilimleme, girdi 100.000.000 giriş olduğunda saf python filtresinden iki kat daha hızlıydı.

In [321]: r = numpy.random.uniform(0, 1, 100000000)

In [322]: %timeit test1(r) # filter
1 loops, best of 3: 21.3 s per loop

In [323]: %timeit test2(r) # sort and slice
1 loops, best of 3: 11.1 s per loop

In [324]: %timeit test3(r) # boolean indexing
1 loops, best of 3: 1.26 s per loop

2
evet, oldukça güzel :-) kodun yürütülmesi çok az zaman alıyorsa, ölçümlerin ortalamasını almak için kaç yineleme yapması gerektiğini otomatik olarak hesaplıyor
fortran

5
@yosukesabai - IPython %timeityerleşik timeitmodülü kullanıyor . Şuna da bir göz at. docs.python.org/library/timeit.html
Joe Kington

Yanıtlar:


112

b = a[a>threshold] bu yapmalı

Aşağıdaki gibi test ettim:

import numpy as np, datetime
# array of zeros and ones interleaved
lrg = np.arange(2).reshape((2,-1)).repeat(1000000,-1).flatten()

t0 = datetime.datetime.now()
flt = lrg[lrg==0]
print datetime.datetime.now() - t0

t0 = datetime.datetime.now()
flt = np.array(filter(lambda x:x==0, lrg))
print datetime.datetime.now() - t0

Bende var

$ python test.py
0:00:00.028000
0:00:02.461000

http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays


1
sadece yapması gerektiğini düşündüğüm şeyi değil, test sonucunu ekledi. : p
yosukesabai

3
Bu tür bir indeksleme dizinin boyutunu korumaz, aynı sayıda elemanı tutmak ve alt eşik değerlerini sıfırlamak nasıl mümkün olabilir?
linello

9
@linello, a [a <= eşik] = 0, eşiği aşmayan kısmı maskeleyecek
yosukesabai

4
İki kritere göre filtreleme sorunuyla karşılaştım. İşte çözüm: stackoverflow.com/a/3248599/1373468
Robin Newhouse

@yosukesabai Orijinal değerleri değiştirmeden tam olarak bunu yapmak mümkün mü? Bunu np.mayapmam gerekiyorsa, nasıl yapılacağını çözemiyorum.
embert
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.