wake-up-neo.net

Wie greife ich auf die i-te Spalte eines mehrdimensionalen NumPy-Arrays zu?

Angenommen, ich habe:

test = numpy.array([[1, 2], [3, 4], [5, 6]])

test[i] holt mich ith Zeile des Arrays (zB [1, 2]). Wie kann ich auf die Spalte ith zugreifen? (zB [1, 3, 5]). Wäre dies auch eine teure Operation?

390
lpl
>>> test[:,0]
array([1, 3, 5])

Ähnlich,

>>> test[1,:]
array([3, 4])

ermöglicht den Zugriff auf Zeilen. Dies wird in Abschnitt 1.4 (Indexierung) der NumPy-Referenz behandelt. Das geht schnell, zumindest nach meiner Erfahrung. Es ist sicherlich viel schneller als auf jedes Element in einer Schleife zuzugreifen.

577
mtrw

Und wenn Sie auf mehrere Spalten gleichzeitig zugreifen möchten, können Sie Folgendes tun:

>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
       [3, 5],
       [6, 8]])
61
Akavall
>>> test[:,0]
array([1, 3, 5])

mit diesem Befehl erhalten Sie einen Zeilenvektor. Wenn Sie nur eine Schleife ausführen möchten, ist dies in Ordnung. Wenn Sie jedoch mit einem anderen Array mit der Dimension 3xN hacken möchten, müssen Sie

ValueError: Alle Eingabearrays müssen dieselbe Anzahl von Dimensionen haben

während

>>> test[:,[0]]
array([[1],
       [3],
       [5]])

gibt Ihnen einen Spaltenvektor, damit Sie Verkettungs- oder Stapeloperationen ausführen können.

z.B.

>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
       [3, 4, 3],
       [5, 6, 5]])
48
Cloud

Sie können auch eine Zeile transponieren und zurückgeben:

In [4]: test.T[0]
Out[4]: array([1, 3, 5])
20
Hotschke

Um mehrere und unabhängige Spalten zu erhalten, gehen Sie wie folgt vor:

> test[:,[0,2]]

sie erhalten die Spalten 0 und 2

4
Alberto Perez

Lassen Sie mich einige Nuancen erwähnen, obwohl die Frage beantwortet wurde.

Angenommen, Sie interessieren sich für die erste Spalte des Arrays

arr = numpy.array([[1, 2],
                   [3, 4],
                   [5, 6]])

Wie Sie bereits aus anderen Antworten wissen, verwenden Sie Slicing, um es in Form eines "Zeilenvektors" (Array mit der Form (3,)) zu erhalten:

arr_c1_ref = arr[:, 1]  # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy()  # creates a copy of the 1st column of the arr

Um zu überprüfen, ob ein Array eine Ansicht oder eine Kopie eines anderen Arrays ist, können Sie Folgendes tun:

arr_c1_ref.base is arr  # True
arr_c1_copy.base is arr  # False

siehe ndarray.base .

Abgesehen von dem offensichtlichen Unterschied zwischen den beiden (das Ändern von arr_c1_ref wirkt sich auf arr aus), ist die Anzahl der Byte-Schritte für das Durchlaufen der einzelnen Schritte unterschiedlich:

arr_c1_ref.strides[0]  # 8 bytes
arr_c1_copy.strides[0]  # 4 bytes

siehe Schritte . Warum ist das wichtig? Stellen Sie sich vor, Sie haben ein sehr großes Array A anstelle des arr:

A = np.random.randint(2, size=(10000,10000), dtype='int32')
A_c1_ref = A[:, 1] 
A_c1_copy = A[:, 1].copy()

und Sie möchten die Summe aller Elemente der ersten Spalte berechnen, d. h. A_c1_ref.sum() oder A_c1_copy.sum(). Die Verwendung der kopierten Version ist viel schneller:

%timeit A_c1_ref.sum()  # ~248 µs
%timeit A_c1_copy.sum()  # ~12.8 µs

Dies ist auf die zuvor erwähnte unterschiedliche Anzahl von Schritten zurückzuführen:

A_c1_ref.strides[0]  # 40000 bytes
A_c1_copy.strides[0]  # 4 bytes

Obwohl es den Anschein hat, dass die Verwendung von Spaltenkopien besser ist, ist dies nicht immer der Fall, da das Erstellen einer Kopie Zeit kostet und mehr Speicher benötigt (in diesem Fall habe ich ca. 200 µs zum Erstellen des A_c1_copy benötigt). Wenn wir jedoch die Kopie an erster Stelle benötigen oder viele verschiedene Operationen an einer bestimmten Spalte des Arrays ausführen müssen und Speicher aus Gründen der Geschwindigkeit geopfert werden muss, ist das Erstellen einer Kopie der richtige Weg.

Für den Fall, dass wir hauptsächlich mit Spalten arbeiten möchten, ist es möglicherweise eine gute Idee, unser Array in der Reihenfolge "F" (Spalten-Major) anstelle der Reihenfolge "C" (Zeilen-Major) (Standard) zu erstellen ), und führen Sie dann das Schneiden wie zuvor aus, um eine Spalte zu erhalten, ohne sie zu kopieren:

A = np.asfortranarray(A)  # or np.array(A, order='F')
A_c1_ref = A[:, 1]
A_c1_ref.strides[0]  # 4 bytes
%timeit A_c1_ref.sum()  # ~12.6 µs vs ~248 µs

Die Ausführung der Summenoperation (oder einer anderen) in einer Spaltenansicht ist jetzt viel schneller.

Abschließend möchte ich darauf hinweisen, dass das Transponieren eines Arrays und das Verwenden der Zeilenteilung dasselbe ist wie das Verwenden der Spaltenteilung für das ursprüngliche Array, da das Transponieren nur durch Austauschen der Form und der Schritte des ursprünglichen Arrays erfolgt.

A.T[1,:].strides[0]  # 40000
3
AndyK
>>> test
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> ncol = test.shape[1]
>>> ncol
5L

Dann können Sie die 2. - 4. Spalte folgendermaßen auswählen:

>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
       [6, 7, 8]])
2
mac