Frage

Ich weiß, es ist eine Methode für eine Python-Liste des ersten Index von etwas zurück:

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

Gibt es so etwas wie die für NumPy Arrays?

War es hilfreich?

Lösung

Ja, hier ist die Antwort gegeben ein NumPy Array, array, und ein Wert, item, nach dem gesucht werden:

itemindex = numpy.where(array==item)

Das Ergebnis ist ein Tupel mit zunächst alle Zeilenindizes, dann werden alle Spaltenindizes.

Zum Beispiel, wenn ein Array zwei Dimensionen und es enthielt Ihren Artikel an zwei Standorten dann

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

wäre gleich Ihren Artikel und so würde

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

numpy.where

Andere Tipps

Wenn Sie den Index des ersten Auftretens von nur ein Wert , können Sie nonzero (oder where, die in diesem Fall auf dieselbe 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 der einzelnen viele Werte müssen, könnten Sie natürlich tun das gleiche wie oben wiederholt, aber es gibt einen Trick, der schneller sein kann. Die folgende findet die Indizes des ersten Elements jeden Teilfolge :

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

Beachten Sie, dass es den Beginn der beiden Teilfolge von 3s und beide Untersequenzen von 8s findet:

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

Es ist also etwas anders als das Finden der ersten Vorkommen von jedem Wert. In Ihrem Programm können Sie in der Lage sein, mit einer sortierten Version von t zu arbeiten zu bekommen, was Sie wollen:

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

Sie können auch eine NumPy Array zur Liste in der Luft umwandeln und seinen Index zu bekommen. 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 werden.

Wenn Sie vorhaben, dies als Index in etwas anderes zu verwenden, können Sie boolean Indizes verwenden, wenn die Arrays sind sende; Sie brauchen keine explizite Indizes. Der absolute einfachste Weg, dies zu tun ist, Index auf einem Wahrheitswert einfach basierte.

other_array[first_array == item]

Jeder boolean Betrieb funktioniert:

a = numpy.arange(100)
other_array[first_array > 50]

Die Nicht-Null-Methode nimmt booleans auch:

index = numpy.nonzero(first_array == item)[0][0]

Die beiden Nullen für das Tupel von Indizes sind (unter der Annahme first_array ist 1D) und dann das erste Element in dem Array von Indizes.

Nur ein sehr performant und handlich Alternative basierend auf np.ndenumerate 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 Angebote natürlich mit mehrdimensionalen Arrays :

>>> 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 viel schneller (weil sie den Betrieb Schließen Kurz ist) als jeder Ansatz np.where oder np.nonzero.


np.argwhere könnte auch behandeln anmutig mit multidimensionalen Arrays (Sie manuell es brauchen würden zu einem Tupel werfen und es ist nicht kurzgeschlossen), aber es würde scheitern, wenn keine Übereinstimmung gefunden wird:

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

l.index(x) gibt die kleinsten i , so dass i den Index des ersten Auftretens von x in der Liste ist.

Man kann sicher davon ausgehen, dass die index() Funktion in Python implementiert ist, so dass er stoppt, nachdem das erste Spiel zu finden, und dies führt zu einer optimalen durchschnittlichen Leistung.

Für ein Element nach dem ersten Spiel Anhalten der Suche in einem NumPy Array einen Iterator verwenden ( ndenumerate ).

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,)
Hinweis

, dass beide Methoden index() und next einen Fehler zurück, wenn das Element nicht gefunden wird. Mit next kann man ein zweites Argument verwenden, um einen besonderen Wert für den Fall zurückkehren wird das Element nicht gefunden wird, z.

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

Es gibt auch andere Funktionen in NumPy (argmax, where und nonzero), die verwendet werden kann, ein Element in einem Array zu finden, aber sie haben alle den Nachteil, Blick durch das gesamte Array gehen für alle Vorkommen, wobei damit nicht zum Auffinden des ersten Elements optimiert. Beachten Sie auch, dass where und nonzero Return-Arrays, so müssen Sie das erste Element auszuwählen, 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

überprüfen Sie einfach, dass für großen Arrays der Lösung eines Iterator mit schneller , wenn der gesuchten Artikel am Anfang des Arrays (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 ein offenes NumPy GitHub Ausgabe .

Siehe auch: Numpy: erster Index des Wert schnell finden

Um Index auf beliebigen Kriterien, können Sie so etwas wie folgt aus:

In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
   .....:         print(', '.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4

Und hier ist eine schnelle Funktion, welche list.index () zu tun hat, mit der Ausnahme keine Ausnahme auslösen, wenn sie nicht gefunden wird. Vorsicht - dies wahrscheinlich sehr langsam auf große Arrays ist. Sie können sich wahrscheinlich diesen Affen auf Arrays Patch, wenn Sie es eher als eine Methode verwenden würden.

def ndindex(ndarray, item):
    if len(ndarray.shape) == 1:
        try:
            return [ndarray.tolist().index(item)]
        except:
            pass
    else:
        for i, subarray in enumerate(ndarray):
            try:
                return [i] + ndindex(subarray, item)
            except:
                pass

In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]

Für 1D-Arrays, würde ich np.flatnonzero(array == value)[0] empfehlen, die sowohl np.nonzero(array == value)[0][0] und np.where(array == value)[0][0] gleichwertig ist, aber vermeidet die Hässlichkeit von Unboxing einen 1-Elemente Tupels.

Es gibt viele Operationen in NumPy, die vielleicht zusammen, dies zu erreichen genommen werden können. Dies Indizes der Elemente gleich Punkt zurück:

numpy.nonzero(array - item)

Sie könnte dann die ersten Elemente der Listen ein einzelnes Element zu erhalten.

Für eindimensionale sortiert Arrays, wäre es viel einfacher und effizienter O (log (n)) verwenden numpy.searchsorted , die eine ganze Zahl zurückgibt NumPy (Position). Zum Beispiel:

arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)

So stellen Sie sicher, dass das Array bereits sortiert

Überprüfen Sie auch, ob zurückgegeben Index i tatsächlich das gesuchte Element enthält, da Hauptziel der searchsorted ist Indizes zu finden, wo Elemente zu halten, um eingefügt werden soll.

if arr[i] == 3:
    print("present")
else:
    print("not present")

Eine alternative das erste Element aus np.where zum Auswählen () ist ein Generator Ausdruck verwenden zusammen mit Aufzählen wie:

>>> import numpy as np
>>> x = np.arange(100)   # x = array([0, 1, 2, 3, ... 99])
>>> next(i for i, x_i in enumerate(x) if x_i == 2)
2

Für eine zweidimensionale Anordnung würde man tun:

>>> x = np.arange(100).reshape(10,10)   # x = array([[0, 1, 2,... 9], [10,..19],])
>>> next((i,j) for i, x_i in enumerate(x) 
...            for j, x_ij in enumerate(x_i) if x_ij == 2)
(0, 2)

Der Vorteil dieses Ansatzes ist, dass es verhindert, dass die Elemente des Arrays Überprüfung nach dem ersten Spiel, während np.where prüft alle Elemente für eine Übereinstimmung gefunden wird. Ein Generator Ausdruck würde schneller sein, wenn es früh Spiel in der Anordnung.

Die numpy_indexed Paket (Disclaimer, bin ich sein Autor) ein vektorisiert Äquivalent list.index enthält für numpy.ndarray; das heißt:

sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
arrays_to_query = [[-5, 0], [1, 0]]

import numpy_indexed as npi
idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
print(idx)   # [2, -1]

Diese Lösung hat Leistung vektorisiert, verallgemeinert auf ndarrays und verschiedene Wege für den Umgang mit fehlenden Werten hat.

Hinweis: Dies ist für Python Version 2.7

Sie kann eine Lambda-Funktion verwenden, um mit dem Problem fertig zu werden, und es funktioniert sowohl auf NumPy Array und Liste.

your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]

import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]

Und Sie können mit

result[0]

den ersten Index der gefilterten Elemente erhalten.

Für Python 3.6, verwenden Sie

list(result)

statt

result
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top