605 Stimmen

Gibt es eine NumPy-Funktion, um den ersten Index von etwas in einem Array zurückzugeben?

Ich weiß, es gibt eine Methode für eine Python-Liste, um den ersten Index von etwas zurückzugeben:

>>> l = [1, 2, 3]
>>> l.index(2)
1

Gibt es so etwas auch für NumPy-Arrays?

5 Stimmen

666voto

Alex Punkte 8003

Ja, angesichts eines Arrays, array und einen Wert, item zu suchen, können Sie mit np.where als:

itemindex = numpy.where(array == item)

Das Ergebnis ist ein Tupel, das zuerst alle Zeilenindizes und dann alle Spaltenindizes enthält.

Wenn ein Array zum Beispiel zwei Dimensionen hat und Ihr Element an zwei Stellen enthält, dann

array[itemindex[0][0]][itemindex[1][0]]

wäre gleich Ihrem Artikel und würde so sein:

array[itemindex[0][1]][itemindex[1][1]]

88voto

Vebjorn Ljosa Punkte 16350

Wenn Sie den Index des ersten Vorkommens von nur ein Wert können Sie verwenden nonzero (oder where was in diesem Fall auf dasselbe hinausläuft):

>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])
>>> nonzero(t == 8)
(array([6, 8, 9]),)
>>> nonzero(t == 8)[0][0]
6

Wenn Sie den ersten Index von jedem der viele Werte Sie könnten natürlich das Gleiche wie oben wiederholt tun, aber es gibt einen Trick, der vielleicht schneller ist. Im Folgenden werden die Indizes des ersten Elements der einzelnen Teilsequenz :

>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)

Beachten Sie, dass es den Anfang beider Teilfolgen von 3s und beider Teilfolgen von 8s findet:

[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]

Es ist also etwas anders als die Suche nach der ersten Vorkommen eines jeden Wertes. In Ihrem Programm können Sie möglicherweise mit einer sortierten Version von t um zu bekommen, was Sie wollen:

>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)

70voto

Hima Punkte 10100

Sie können auch ein NumPy-Array in eine Liste umwandeln und seinen Index erhalten. Zum Beispiel,

l = [1,2,3,4,5] # Python list
a = numpy.array(l) # NumPy array
i = a.tolist().index(2) # i will return index of 2
print i

Es wird 1 gedruckt.

28voto

MSeifert Punkte 131411

Nur um eine sehr leistungsfähige und praktische numba Alternative basierend auf np.ndenumerate um den ersten Index zu finden:

from numba import njit
import numpy as np

@njit
def index(array, item):
    for idx, val in np.ndenumerate(array):
        if val == item:
            return idx
    # If no item was found return None, other return types might be a problem due to
    # numbas type inference.

Das ist ziemlich schnell und geht natürlich mit mehrdimensionalen Arrays um :

>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2

>>> index(arr1, 2)
(2, 2, 2)

>>> arr2 = np.ones(20)
>>> arr2[5] = 2

>>> index(arr2, 2)
(5,)

Dies kann sein wesentlich schneller (weil es den Vorgang kurzschließt) als jeder Ansatz, der np.where o np.nonzero .


Allerdings np.argwhere könnte auch mit anmutig mit mehrdimensionalen Arrays (Sie müssten sie manuell in ein Tupel umwandeln) y er ist nicht kurzgeschlossen), aber er würde fehlschlagen, wenn keine Übereinstimmung gefunden wird:

>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)

20voto

user2314737 Punkte 23784

l.index(x) gibt die kleinste i tal que i ist der Index des ersten Vorkommens von x in der Liste.

Man kann sicher davon ausgehen, dass die index() Funktion in Python ist so implementiert, dass sie nach dem Finden der ersten Übereinstimmung anhält, was zu einer optimalen durchschnittlichen Leistung führt.

Um ein Element zu finden, das nach der ersten Übereinstimmung in einem NumPy-Array stehen bleibt, verwenden Sie einen Iterator ( ndenumerieren ).

In [67]: l=range(100)

In [68]: l.index(2)
Out[68]: 2

NumPy-Array:

In [69]: a = np.arange(100)

In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)

Beachten Sie, dass beide Methoden index() et next einen Fehler zurückgeben, wenn das Element nicht gefunden wird. Mit next kann man ein zweites Argument verwenden, um einen speziellen Wert zurückzugeben, falls das Element nicht gefunden wird, z. B.

In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)

Es gibt weitere Funktionen in NumPy ( argmax , where y nonzero ), die verwendet werden können, um ein Element in einem Array zu finden, aber sie haben alle den Nachteil, dass sie das gesamte Array durchgehen und nach alle Vorkommen und ist somit nicht für das Auffinden des ersten Elements optimiert. Beachten Sie auch, dass where et nonzero geben Arrays zurück, so dass Sie das erste Element auswählen müssen, um den Index zu erhalten.

In [71]: np.argmax(a==2)
Out[71]: 2

In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)

In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)

Zeitvergleich

Ich überprüfe nur, dass die Lösung mit einem Iterator bei großen Arrays schneller ist wenn das gesuchte Element am Anfang des Arrays steht (mit %timeit in der IPython-Shell):

In [285]: a = np.arange(100000)

In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop

In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop

In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop

Dies ist eine offene NumPy GitHub Ausgabe .

Siehe auch: Numpy: den ersten Index eines Wertes schnell finden

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X