Auf diese Weise verwendet numpy die erweiterte Indizierung, um Array-Formen zu senden. Wenn Sie a 0
für den ersten und y
für den letzten Index übergeben, sendet numpy 0
die gleiche Form wie y
. Folgende Äquivalenz gilt : x[0,:,:,y] == x[(0, 0, 0),:,:,y]
. Hier ist ein Beispiel
import numpy as np
x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])
np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True
Da Sie nun effektiv zwei Indexsätze übergeben, verwenden Sie die erweiterte Indexierungs-API, um (in diesem Fall) Indexpaare zu bilden.
x[(0, 0, 0),:,:,y])
# equivalent to
[
x[0,:,:,y[0]],
x[0,:,:,y[1]],
x[0,:,:,y[2]]
]
# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]
# equivalent to
[
x[r,:,:,c] for r, c in zip(rows, columns)
]
Welches hat eine erste Dimension, die der Länge von entspricht y
. Das sehen Sie.
Schauen Sie sich als Beispiel ein Array mit 4 Dimensionen an, die im nächsten Abschnitt beschrieben werden:
x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])
# x looks like:
array([[[[ 0, 1, 2, 3, 4], -+ =+
[ 5, 6, 7, 8, 9], Sheet1 |
[ 10, 11, 12, 13, 14], | |
[ 15, 16, 17, 18, 19]], -+ |
Workbook1
[[ 20, 21, 22, 23, 24], -+ |
[ 25, 26, 27, 28, 29], Sheet2 |
[ 30, 31, 32, 33, 34], | |
[ 35, 36, 37, 38, 39]], -+ |
|
[[ 40, 41, 42, 43, 44], -+ |
[ 45, 46, 47, 48, 49], Sheet3 |
[ 50, 51, 52, 53, 54], | |
[ 55, 56, 57, 58, 59]]], -+ =+
[[[ 60, 61, 62, 63, 64],
[ 65, 66, 67, 68, 69],
[ 70, 71, 72, 73, 74],
[ 75, 76, 77, 78, 79]],
[[ 80, 81, 82, 83, 84],
[ 85, 86, 87, 88, 89],
[ 90, 91, 92, 93, 94],
[ 95, 96, 97, 98, 99]],
[[100, 101, 102, 103, 104],
[105, 106, 107, 108, 109],
[110, 111, 112, 113, 114],
[115, 116, 117, 118, 119]]]])
x
hat eine wirklich leicht verständliche sequentielle Form, mit der wir jetzt zeigen können, was passiert ...
Die erste Dimension entspricht 2 Excel-Arbeitsmappen, die zweite Dimension entspricht 3 Blättern in jeder Arbeitsmappe, die dritte Dimension entspricht 4 Zeilen pro Blatt und die letzte Dimension besteht aus 5 Werten für jede Zeile (oder Spalten pro Blatt).
Wenn man es so betrachtet und danach fragt x[0,:,:,0]
, lautet das Sprichwort: "Geben Sie mir in der ersten Arbeitsmappe für jedes Blatt, für jede Zeile den ersten Wert / die erste Spalte."
x[0,:,:,y[0]]
# returns:
array([[ 0, 5, 10, 15],
[20, 25, 30, 35],
[40, 45, 50, 55]])
# this is in the same as the first element in:
x[(0,0,0),:,:,y]
Aber jetzt mit erweiterter Indizierung können wir uns vorstellen, dass x[(0,0,0),:,:,y]
"in der ersten Arbeitsmappe für jedes Blatt, für jede Zeile der y
th-Wert / die Spalte angegeben wird. Ok, machen Sie es jetzt für jeden Wert von y
".
x[(0,0,0),:,:,y]
# returns:
array([[[ 0, 5, 10, 15],
[20, 25, 30, 35],
[40, 45, 50, 55]],
[[ 2, 7, 12, 17],
[22, 27, 32, 37],
[42, 47, 52, 57]],
[[ 4, 9, 14, 19],
[24, 29, 34, 39],
[44, 49, 54, 59]]])
Wo es verrückt wird, ist, dass numpy gesendet wird, um dem zu entsprechen äußeren Dimensionen des Index-Arrays zu entsprechen. Wenn Sie also denselben Vorgang wie oben ausführen möchten, jedoch für BEIDE "Excel-Arbeitsmappen", müssen Sie keine Schleifen erstellen und verketten. Sie können ein Array einfach an die erste Dimension übergeben, es MUSS jedoch eine kompatible Form haben.
Das Übergeben einer Ganzzahl wird an gesendet y.shape == (3,)
. Wenn Sie ein Array als ersten Index übergeben möchten, muss nur die letzte Dimension des Arrays kompatibel sein y.shape
. Das heißt, die letzte Dimension des ersten Index muss entweder 3 oder 1 sein.
ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)
ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)
ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)
Eine kurze Erklärung in den Dokumenten gefunden: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing
Bearbeiten:
Aus der ursprünglichen Frage können Sie einen Einzeiler Ihres gewünschten Subslicing verwenden x[0][:,:,y]
:
x[0][:,:,y].shape
# returns
(2, 50, 3)
Wenn Sie es jedoch versuchen , diesen Subslices zuzuweisen , müssen Sie sehr vorsichtig sein, dass Sie eine Shared-Memory-Ansicht des ursprünglichen Arrays betrachten. Andernfalls erfolgt die Zuordnung nicht zum ursprünglichen Array, sondern zu einer Kopie.
Shared Memory tritt nur auf, wenn Sie eine Ganzzahl oder ein Slice verwenden, um Ihr Array zu unterteilen, dh x[:,0:3,:,:]
oder x[0,:,:,1:-1]
.
np.shares_memory(x, x[0])
# returns:
True
np.shares_memory(x, x[:,:,:,y])
# returns:
False
Sowohl in Ihrer ursprünglichen Frage als auch in meinem Beispiel y
handelt es sich weder um ein Int noch um ein Slice. Daher wird immer eine Kopie des Originals zugewiesen.
ABER! Weil Ihre Array für y
als eine Scheibe ausgedrückt werden, Sie CAN tatsächlich über eine frei belegbare Ansicht Ihres Array erhalten:
x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)
np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True
# actually assigns to the original array
x[0,:,:,0:21:10] = 100
Hier verwenden wir das Slice 0:21:10
, um jeden Index zu erfassen, der sich in befinden würde range(0,21,10)
. Wir müssen verwenden 21
und nicht20
weil der Stopppunkt wie in der range
Funktion vom Slice ausgeschlossen ist .
Wenn Sie also ein Slice erstellen können, das Ihren Subslicing-Kriterien entspricht, können Sie eine Zuweisung vornehmen.