web-dev-qa-db-de.com

Was ist der effizienteste Weg, um zu überprüfen, ob ein Wert in einem NumPy-Array vorhanden ist?

Ich habe ein sehr großes NumPy-Array

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

Ich möchte überprüfen, ob in der 1. Spalte des Arrays ein Wert vorhanden ist. Ich habe eine Reihe von einheimischen Methoden (beispielsweise durchlaufen jede Zeile und Überprüfung), aber angesichts der Größe des Arrays würde ich gerne die effizienteste Methode finden.

Vielen Dank!

42
thegreatt

Wie wäre es mit

if value in my_array[:, col_num]:
    do_whatever

Edit: Ich denke, __contains__ ist so implementiert, dass dies der Version von @ detly entspricht

50
agf

Das offensichtlichste für mich wäre:

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

Um mehrere Werte zu überprüfen, können Sie numpy.in1d ​​() verwenden. Dies ist eine elementweise Funktionsversion des Python-Schlüsselworts. Wenn Ihre Daten sortiert sind, können Sie numpy.searchsorted () verwenden:

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

Faszinierend. Ich musste die Geschwindigkeit einer Reihe von Schleifen verbessern, die auf dieselbe Weise die Indexfindung durchführen müssen. Also entschied ich mich, alle Lösungen hier zusammen mit einigen Riffs auszuprobieren.

Hier sind meine Geschwindigkeitstests für 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

Sehr überraschend! Größenordnungsunterschied!

Zusammenfassend, wenn Sie nur wissen möchten, ob sich etwas in einer 1D-Liste befindet oder nicht:

  • 19s N.any (N.in1d ​​(numpy array)) 
  • 15s x in (Liste) 
  • 8s N.any (x == numpy array) 
  • 6s x in (numpy array) 
  • .1s x in (set oder ein Wörterbuch)

Wenn Sie wissen möchten, wo sich auch etwas in der Liste befindet (Reihenfolge ist wichtig):

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

Das Hinzufügen von @ HYRYs Antwort in1d scheint für numpy am schnellsten zu sein. Dies verwendet Numpy 1.8 und Python 2.7.6.

In1d war in diesem Test am schnellsten:

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

Die Verwendung eines Python-Sets scheint am schnellsten zu sein:

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

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

Der für mich bequemste Weg ist:

(Val in X[:, col_num])

dabei ist Val der Wert, nach dem Sie suchen möchten, und X ist das Array. Angenommen, Sie möchten prüfen, ob der Wert 8 in der dritten Spalte vorhanden ist. Einfach schreiben

(8 in X[:, 2])

Dies gibt True zurück, wenn in der dritten Spalte 8 steht, andernfalls False.

0
Loochie