Ich habe Probleme, die spezifischen Spalten pro Zeile einer NumPy
Matrix auszuwählen .
Angenommen, ich habe die folgende Matrix, die ich nennen würde X
:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Ich habe auch einen list
Spaltenindex pro Zeile, den ich aufrufen würde Y
:
[1, 0, 2]
Ich muss die Werte erhalten:
[2]
[4]
[9]
Anstelle von a list
mit Indizes Y
kann ich auch eine Matrix mit der gleichen Form erstellen, X
in der jede Spalte ein bool
/ int
im Bereich von 0 bis 1 ist, was angibt, ob dies die erforderliche Spalte ist.
[0, 1, 0]
[1, 0, 0]
[0, 0, 1]
Ich weiß, dass dies durch Iterieren über das Array und Auswählen der benötigten Spaltenwerte erreicht werden kann. Dies wird jedoch häufig auf großen Datenfeldern ausgeführt und muss daher so schnell wie möglich ausgeführt werden.
Ich habe mich also gefragt, ob es eine bessere Lösung gibt.
Vielen Dank.
quelle
Antworten:
Wenn Sie ein boolesches Array haben, können Sie auf dieser Grundlage eine direkte Auswahl treffen:
>>> a = np.array([True, True, True, False, False]) >>> b = np.array([1,2,3,4,5]) >>> b[a] array([1, 2, 3])
Um Ihrem ersten Beispiel zu folgen, können Sie Folgendes tun:
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> b = np.array([[False,True,False],[True,False,False],[False,False,True]]) >>> a[b] array([2, 4, 9])
Sie können auch eine hinzufügen
arange
und eine direkte Auswahl treffen, je nachdem, wie Sie Ihr boolesches Array generieren und wie Ihr Code wie YMMV aussieht.>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> a[np.arange(len(a)), [1,0,2]] array([2, 4, 9])
Hoffe das hilft, lass es mich wissen, wenn du weitere Fragen hast.
quelle
arange
. Dies war besonders nützlich für mich, um verschiedene Blöcke aus mehreren Matrizen abzurufen (also im Grunde der 3D-Fall dieses Beispiels)arange
statt verwenden müssen:
? Ich weiß, dass dein Weg funktioniert und meiner nicht, aber ich würde gerne verstehen, warum.:
Syntax nicht auf die gleiche Weise funktioniert.:
bedeutet mein Verständnis, dass das Mischen mit der erweiterten Indizierung bedeutet: "Wenden Sie für jeden Unterraum:
die angegebene erweiterte Indizierung an". Ist mein Verständnis richtig?Sie können so etwas tun:
In [7]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [8]: lst = [1, 0, 2] In [9]: a[np.arange(len(a)), lst] Out[9]: array([2, 4, 9])
Weitere Informationen zum Indizieren mehrdimensionaler Arrays: http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays
quelle
:
werdenlen(a)
stattdessen mehrere Ergebnisse ausgegeben , wobei angegeben wird , dass der Index jeder Zeile die erwarteten Ergebnisse druckt.Ein einfacher Weg könnte aussehen wie:
In [1]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [2]: y = [1, 0, 2] #list of indices we want to select from matrix 'a'
range(a.shape[0])
wird zurückkehrenarray([0, 1, 2])
In [3]: a[range(a.shape[0]), y] #we're selecting y indices from every row Out[3]: array([2, 4, 9])
quelle
Neuere
numpy
Versionen haben eintake_along_axis
(undput_along_axis
) hinzugefügt , das diese Indizierung sauber durchführt.In [101]: a = np.arange(1,10).reshape(3,3) In [102]: b = np.array([1,0,2]) In [103]: np.take_along_axis(a, b[:,None], axis=1) Out[103]: array([[2], [4], [9]])
Es funktioniert wie folgt:
In [104]: a[np.arange(3), b] Out[104]: array([2, 4, 9])
aber mit unterschiedlicher Achshandhabung. Es zielt insbesondere darauf ab, die Ergebnisse von
argsort
und anzuwendenargmax
.quelle
Sie können dies mit dem Iterator tun. So was:
np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)
Zeit:
N = 1000 X = np.zeros(shape=(N, N)) Y = np.arange(N) #@Aशwini चhaudhary %timeit X[np.arange(len(X)), Y] 10000 loops, best of 3: 30.7 us per loop #mine %timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 1000 loops, best of 3: 1.15 ms per loop #mine %timeit np.diag(X.T[Y]) 10 loops, best of 3: 20.8 ms per loop
quelle
np.diag(X.T[Y])
ist so langsam ... abernp.diag(X.T)
ist so schnell (10us). Ich weiß nicht warum.Eine andere clevere Möglichkeit besteht darin, das Array zuerst zu transponieren und anschließend zu indizieren. Nehmen Sie zum Schluss die Diagonale, es ist immer die richtige Antwort.
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) Y = np.array([1, 0, 2, 2]) np.diag(X.T[Y])
Schritt für Schritt:
Original-Arrays:
>>> X array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]]) >>> Y array([1, 0, 2, 2])
Transponieren, um es richtig zu indizieren.
>>> X.T array([[ 1, 4, 7, 10], [ 2, 5, 8, 11], [ 3, 6, 9, 12]])
Holen Sie sich Zeilen in der Y-Reihenfolge.
>>> X.T[Y] array([[ 2, 5, 8, 11], [ 1, 4, 7, 10], [ 3, 6, 9, 12], [ 3, 6, 9, 12]])
Die Diagonale sollte jetzt klar werden.
>>> np.diag(X.T[Y]) array([ 2, 4, 9, 12]
quelle