webentwicklung-frage-antwort-db.com.de

Numpy: Suchen Sie für jedes Element in einem Array den Index in einem anderen Array

Ich habe zwei 1D-Arrays, x und y, eines kleiner als das andere. Ich versuche, den Index jedes Elements von y in x zu finden.

Ich habe zwei naive Wege gefunden, dies zu tun, der erste ist langsam und der zweite speicherintensiv.

Der langsame Weg

indices= []
for iy in y:
    indices += np.where(x==iy)[0][0]

Das Gedächtnis

xe = np.outer([1,]*len(x), y)
ye = np.outer(x, [1,]*len(y))
junk, indices = np.where(np.equal(xe, ye))

Gibt es einen schnelleren oder weniger speicherintensiven Ansatz? Im Idealfall würde die Suche die Tatsache ausnutzen, dass wir nicht nur eine Sache, sondern viele Dinge in einer Liste suchen und daher der Parallelisierung etwas zugänglicher sind. Bonuspunkte, wenn Sie nicht jedes Element annehmen von y ist eigentlich in x. 

31
Chris

Wie Joe Kington sagte, kann searchsorted () ein Element sehr schnell suchen. Um mit Elementen zu arbeiten, die sich nicht in x befinden, können Sie das Suchergebnis mit dem ursprünglichen y überprüfen und ein maskiertes Array erstellen:

import numpy as np
x = np.array([3,5,7,1,9,8,6,6])
y = np.array([2,1,5,10,100,6])

index = np.argsort(x)
sorted_x = x[index]
sorted_index = np.searchsorted(sorted_x, y)

yindex = np.take(index, sorted_index, mode="clip")
mask = x[yindex] != y

result = np.ma.array(yindex, mask=mask)
print result

das Ergebnis ist:

[-- 3 1 -- -- 6]
20
HYRY

Ich möchte eine einzeilige Lösung vorschlagen:

indices = np.where(np.in1d(x, y))[0]

Das Ergebnis ist ein Array mit Indizes für x-Array, das Elementen aus y entspricht, die in x gefunden wurden.

Man kann es ohne numpy.where benutzen, wenn es nötig ist.

23
RomanS

Wie wäre es damit? 

Es wird davon ausgegangen, dass jedes Element von y in x ist (und Ergebnisse auch für Elemente zurückgibt, die nicht!), Aber es ist viel schneller.

import numpy as np

# Generate some example data...
x = np.arange(1000)
np.random.shuffle(x)
y = np.arange(100)

# Actually preform the operation...
xsorted = np.argsort(x)
ypos = np.searchsorted(x[xsorted], y)
indices = xsorted[ypos]
16
Joe Kington

Ich würde das einfach machen:

indices = np.where(y[:, None] == x[None, :])[1]

Im Gegensatz zu Ihrer Art des Gedächtnisses verwendet Broadcast die direkte Erzeugung von 2D-Boolean-Arrays, ohne dass 2D-Arrays für x und y erstellt werden müssen.

3
Jun Saito

Das Paket numpy_indexed (Disclaimer: Ich bin sein Autor) enthält eine Funktion, die genau dies tut:

import numpy_indexed as npi
indices = npi.indices(x, y, missing='mask')

Es wird derzeit ein KeyError ausgelöst, wenn nicht alle Elemente in y in x vorhanden sind. aber vielleicht sollte ich ein kwarg hinzufügen, damit man solche Elemente mit -1 oder etwas markieren kann.

Es sollte dieselbe Effizienz wie die derzeit akzeptierte Antwort haben, da die Implementierung in ähnlicher Weise verläuft. numpy_indexed ist jedoch flexibler und ermöglicht beispielsweise die Suche nach Indizes von Zeilen mehrdimensionaler Arrays.

BEARBEITEN: ive hat die Behandlung fehlender Werte geändert; Der "fehlende" Kwarg kann jetzt mit "Raise", "Ignorieren" oder "Maske" gesetzt werden. Im letzteren Fall erhalten Sie ein maskiertes Array mit der gleichen Länge von y, in dem Sie .compressed () aufrufen können, um die gültigen Indizes zu erhalten. Beachten Sie, dass es auch npi.contains (x, y) gibt, wenn Sie dies alles wissen müssen. 

3

Verwenden Sie diese Codezeile: -

indizes = np.where (y [:, None] == x [None,:]) [1]

1
Kaushal Gupta

Ich denke, das ist eine klarere Version:

np.where(y.reshape(y.size, 1) == x)[1]

als indices = np.where(y[:, None] == x[None, :])[1]. Sie müssen x nicht in 2D übertragen. 

Diese Art Lösung fand ich am besten, da anders als auf searchsorted () oder in1d () basierende Lösungen, die hier oder anderswo veröffentlicht wurden, die oben genannten Funktionen mit Duplikaten funktionieren und es egal ist, ob etwas sortiert wird. Das war wichtig für mich, weil ich wollte, dass x in einer bestimmten Reihenfolge ist. 

1
hermidalc

Eine direktere Lösung, die nicht erwartet, dass das Array sortiert wird. 

import pandas as pd
A = pd.Series(['amsterdam', 'delhi', 'chromepet', 'tokyo', 'others'])
B = pd.Series(['chromepet', 'tokyo', 'tokyo', 'delhi', 'others'])

# Find index position of B's items in A
B.map(lambda x: np.where(A==x)[0][0]).tolist()

Ergebnis ist:

[2, 3, 3, 1, 4]
0
Selva