web-dev-qa-db-fra.com

Filtre de seuillage efficace d'un tableau avec numpy

Je dois filtrer un tableau pour supprimer les éléments inférieurs à un certain seuil. Mon code actuel est comme ceci:

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

Le problème est que cela crée une liste temporaire, en utilisant un filtre avec une fonction lambda (lente).

Comme il s’agit d’une opération assez simple, il existe peut-être une fonction numpy qui le fait de manière efficace, mais j’ai été incapable de la trouver.

J'ai pensé qu'un autre moyen d'y parvenir pourrait être de trier le tableau, de trouver l'index du seuil et de renvoyer une tranche à partir de cet index, mais même si cela serait plus rapide pour de petites entrées (et ce ne sera pas perceptible de toute façon). ), son efficacité est asymptotiquement moins efficace à mesure que la taille de l’entrée augmente.

Des idées? Merci!

Mise à jour: J'ai également pris quelques mesures, et le tri + le découpage était encore deux fois plus rapide que le filtre pur python lorsque l'entrée était de 100 000 000 entrées.

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
72
fortran

b = a[a>threshold] cela devrait faire

J'ai testé comme suit:

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

J'ai eu

$ 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

104
yosukesabai