web-dev-qa-db-fra.com

Quel est le moyen le plus efficace de vérifier si une valeur existe dans un tableau NumPy?

J'ai un très grand tableau NumPy

1 40 3
4 50 4
5 60 7
5 49 6
6 70 8
8 80 9
8 72 1
9 90 7
.... 

Je veux vérifier si une valeur existe dans la 1ère colonne du tableau. J'ai pas mal de méthodes maison (par exemple, parcourir chaque ligne et vérifier), mais étant donné la taille du tableau, j'aimerais trouver la méthode la plus efficace.

Merci!

42
thegreatt

Que diriez-vous

if value in my_array[:, col_num]:
    do_whatever

Edit: Je pense que __contains__ est implémenté de telle manière que cela soit identique à la version de @ detly

50
agf

Le plus évident pour moi serait:

np.any(my_array[:, 0] == value)
33
detly

Pour vérifier plusieurs valeurs, vous pouvez utiliser numpy.in1d ​​(), qui est une version fonction par élément du mot clé python po. Si vos données sont triées, vous pouvez utiliser numpy.searchsorted ():

import numpy as np
data = np.array([1,4,5,5,6,8,8,9])
values = [2,3,4,6,7]
print np.in1d(values, data)

index = np.searchsorted(data, values)
print data[index] == values
30
HYRY

Fascinant. Je devais améliorer la vitesse d'une série de boucles devant effectuer la détermination de l'index d'appariement de la même manière. J'ai donc décidé de chronométrer toutes les solutions ici, avec quelques riffs.

Voici mes tests de vitesse pour Python 2.7.10:

import timeit
timeit.timeit('N.any(N.in1d(sids, val))', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

18.86137104034424

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = [20010401010101+x for x in range(1000)]')

15.061666011810303

timeit.timeit('N.in1d(sids, val)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

11.613027095794678

timeit.timeit('N.any(val == sids)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

7.670552015304565

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

5.610057830810547

timeit.timeit('val == sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

1.6632978916168213

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = set([20010401010101+x for x in range(1000)])')

0.0548710823059082

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = dict(Zip([20010401010101+x for x in range(1000)],[True,]*1000))')

0.054754018783569336

Très surprenant! Ordre de grandeur différence!

Pour résumer, si vous voulez juste savoir si quelque chose est dans une liste 1D ou non:

  • 19s N.any (N.in1d ​​(tableau numpy)) 
  • 15s x in (liste) 
  • 8s N.any (x == numpy array) 
  • 6s x in (tableau numpy) 
  • .1s x in (ensemble ou un dictionnaire)

Si vous voulez également savoir où se trouve quelque chose dans la liste (l'ordre est important):

  • 12s N.in1d ​​(x, tableau numpy)
  • 2s x == (tableau numpy)
10
Lukas Mandrake

Ajouter à la réponse de @ HYRY in1d semble être le plus rapide pour numpy. Ceci utilise numpy 1.8 et python 2.7.6.

Dans ce test, in1d était le plus rapide:

a = arange(0,99999,3)
%timeit 10 in a
%timeit in1d(a, 10)

10000 loops, best of 3: 150 µs per loop
10000 loops, best of 3: 61.9 µs per loop

Utiliser un ensemble Python semble être le plus rapide:

s = set(range(0, 99999, 3))
%timeit 10 in s

10000000 loops, best of 3: 47 ns per loop
1
Joelmob

Le moyen le plus pratique selon moi est:

(Val in X[:, col_num])

où Val est la valeur que vous souhaitez vérifier et X le tableau. Dans votre exemple, supposons que vous souhaitiez vérifier si la valeur 8 existe dans la troisième colonne. Écrivez simplement

(8 in X[:, 2])

Cela retournera Vrai si 8 est là dans la troisième colonne, sinon Faux.

0
Loochie