Antworten:
Ja, hier ist die Antwort mit einem NumPy-Array array
und einem Wert item
, nach dem gesucht werden soll:
itemindex = numpy.where(array==item)
Das Ergebnis ist ein Tupel mit zuerst allen Zeilenindizes und dann allen Spaltenindizes.
Wenn ein Array beispielsweise 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 so würde
array[itemindex[0][1]][itemindex[1][1]]
rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
np.argwhere
wäre hier etwas nützlicher:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
where
funktioniert auf jedem Array und gibt ein Tupel der Länge 3 zurück, wenn es auf einem 3D-Array usw. verwendet wird.
Wenn Sie den Index des ersten Auftretens nur eines Werts benötigen , können Sie Folgendes verwenden nonzero
(oder where
, was in diesem Fall dasselbe bedeutet):
>>> 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 für jeden von vielen Werten benötigen , können Sie natürlich wiederholt dasselbe wie oben tun, aber es gibt einen Trick, der möglicherweise schneller ist. Im Folgenden werden die Indizes des ersten Elements jeder Teilsequenz ermittelt :
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
Beachten Sie, dass der Anfang beider Teilsequenzen von 3s und beider Teilsequenzen von 8s gefunden wird:
[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]
Es ist also etwas anders als das erste zu finden Auftreten jedes Werts zu finden. In Ihrem Programm können Sie möglicherweise mit einer sortierten Version von arbeiten t
, um das zu erhalten, was Sie möchten:
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
r_
ist?
r_
verkettet; oder genauer gesagt, es übersetzt Slice-Objekte in Verkettung entlang jeder Achse. Ich hätte hstack
stattdessen verwenden können; das mag weniger verwirrend gewesen sein. Weitere Informationen finden Sie in der Dokumentationr_
. Es gibt auch eine c_
.
vals, locs = np.unique(t, return_index=True)
Sie können auch ein NumPy-Array in eine Liste in der Luft konvertieren und dessen Index abrufen. 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.
[find_list.index(index_list[i]) for i in range(len(index_list))]
find_list
in ein NumPy-Array von object
(oder etwas Spezifischerem, das angemessen ist) konvertieren und es einfach tun find_arr[index_list]
.
Nur um eine sehr performante und handliche hinzuzufügen numbaAlternative 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.
Dies ist ziemlich schnell und befasst sich 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 sein (weil es die Operation kurzschließt) als jeder Ansatz, der np.where
oder verwendet np.nonzero
.
Allerdings np.argwhere
könnte auch behandeln anmutig mit mehrdimensionalen Arrays (Sie würden müssen manuell in ein Tupel geworfen es 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,)
@njit
ist eine Abkürzung von jit(nopython=True)
dh die Funktion wird zum Zeitpunkt des ersten Durchlaufs im laufenden Betrieb vollständig kompiliert, sodass die Python-Interpreter-Aufrufe vollständig entfernt werden.
Wenn Sie dies als Index für etwas anderes verwenden möchten, können Sie boolesche Indizes verwenden, wenn die Arrays sendbar sind. Sie benötigen keine expliziten Indizes. Der absolut einfachste Weg, dies zu tun, besteht darin, einfach basierend auf einem Wahrheitswert zu indizieren.
other_array[first_array == item]
Jede boolesche Operation funktioniert:
a = numpy.arange(100)
other_array[first_array > 50]
Die Nicht-Null-Methode verwendet auch Boolesche Werte:
index = numpy.nonzero(first_array == item)[0][0]
Die beiden Nullen stehen für das Tupel von Indizes (vorausgesetzt, first_array ist 1D) und dann für das erste Element im Array von Indizes.
l.index(x)
Gibt das kleinste i zurück , sodass i der Index des ersten Auftretens von x in der Liste ist.
Man kann davon ausgehen, dass die index()
Funktion in Python so implementiert ist, dass sie nach dem Finden der ersten Übereinstimmung stoppt, und dies führt zu einer optimalen Durchschnittsleistung.
Verwenden Sie einen Iterator ( ndenumerate ) , um ein Element zu finden, das nach der ersten Übereinstimmung in einem NumPy-Array stoppt .
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()
und 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
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 , daß durch die ganze Reihe gehen auf der Suche nach allen Vorkommen, also nicht zum Auffinden des ersten Elements optimiert. Beachten Sie auch das where
und nonzero
geben Sie Arrays zurück, sodass Sie das erste Element auswählen müssen, um den Index abzurufen.
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),)
Wenn Sie nur überprüfen, ob bei großen Arrays die Lösung mithilfe eines Iterators schneller ist, wenn sich das gesuchte Element am Anfang des Arrays befindet (mithilfe %timeit
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-Problem .
Siehe auch: Numpy: Finden Sie schnell den ersten Wertindex
%timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))
? Wenn Sie sich fragen, warum es 1000-mal langsamer ist, dann deshalb, weil Python-Loops über numpy Arrays notorisch langsam sind.
argmax
und where
in diesem Fall viel schneller sind (gesuchtes Element am Ende des Arrays)
Für eindimensional sortierte Arrays wäre es viel einfacher und effizienter, O (log (n)) zu verwenden, indem numpy.searchsorted verwendet wird, das eine NumPy-Ganzzahl (Position) zurückgibt. Zum Beispiel,
arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)
Stellen Sie einfach sicher, dass das Array bereits sortiert ist
Überprüfen Sie auch, ob der zurückgegebene Index i tatsächlich das gesuchte Element enthält, da das Hauptziel von searchsorted darin besteht, Indizes zu finden, in die Elemente eingefügt werden sollen, um die Reihenfolge aufrechtzuerhalten.
if arr[i] == 3:
print("present")
else:
print("not present")
Um nach Kriterien zu indizieren, können Sie so etwas wie das Folgende tun:
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, um das zu tun, was list.index () tut, außer dass keine Ausnahme ausgelöst wird, wenn sie nicht gefunden wird. Achtung - dies ist bei großen Arrays wahrscheinlich sehr langsam. Sie können dies wahrscheinlich auf Arrays patchen, wenn Sie es lieber als Methode verwenden möchten.
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]
Eine Alternative zur Auswahl des ersten Elements aus np.where () besteht darin, einen Generatorausdruck zusammen mit enumerate zu verwenden, z.
>>> 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 ein zweidimensionales Array 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 besteht darin, dass die Überprüfung der Elemente des Arrays nach dem Auffinden der ersten Übereinstimmung beendet wird, während np.where alle Elemente auf Übereinstimmung überprüft. Ein Generatorausdruck wäre schneller, wenn es früh im Array eine Übereinstimmung gibt.
None
als Fallback zurückkehren würde, würde es werden next((i for i, x_i in enumerate(x) if x_i == 2), None)
.
In NumPy gibt es viele Operationen, die möglicherweise zusammengestellt werden könnten, um dies zu erreichen. Dies gibt Indizes von Elementen zurück, die gleich item sind:
numpy.nonzero(array - item)
Sie können dann die ersten Elemente der Listen verwenden, um ein einzelnes Element zu erhalten.
Das numpy_indexed- Paket (Haftungsausschluss, ich bin sein Autor) enthält ein vektorisiertes Äquivalent von list.index für numpy.ndarray; das ist:
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 die Leistung vektorisiert, auf ndarrays verallgemeinert und bietet verschiedene Möglichkeiten, mit fehlenden Werten umzugehen.
Hinweis: Dies gilt für Python 2.7
Sie können eine Lambda-Funktion verwenden, um das Problem zu beheben. Sie funktioniert sowohl für das NumPy-Array als auch für die 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 du kannst verwenden
result[0]
um den ersten Index der gefilterten Elemente zu erhalten.
Verwenden Sie für Python 3.6
list(result)
anstatt
result
<filter object at 0x0000027535294D30>
zu Python 3 (getestet unter Python 3.6.3). Vielleicht Update für Python 3?