W ten sposób numpy wykorzystuje zaawansowane indeksowanie do rozgłaszania kształtów tablic. Kiedy zdasz a 0dla pierwszego indeksu i ydla ostatniego indeksu, numpy wyemituje 0ten sam kształt co y. Zachodzi równoważność: x[0,:,:,y] == x[(0, 0, 0),:,:,y]. Oto przykład
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
Teraz, ponieważ skutecznie przekazujesz dwa zestawy indeksów, używasz zaawansowanego interfejsu API indeksowania do tworzenia (w tym przypadku) par indeksów.
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)
]
Który ma pierwszy wymiar taki sam jak długość y. Oto co widzisz.
Jako przykład spójrz na tablicę z 4 wymiarami opisanymi w następnym fragmencie:
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 ma naprawdę łatwą do zrozumienia sekwencyjną formę, której możemy teraz użyć do pokazania, co się dzieje ...
Pierwszy wymiar przypomina 2 skoroszyty programu Excel, drugi wymiar ma 3 arkusze w każdym skoroszycie, trzeci wymiar ma 4 wiersze na arkusz, a ostatni wymiar to 5 wartości dla każdego wiersza (lub kolumn na arkusz).
Patrząc na to w ten sposób, prosząc x[0,:,:,0], jest powiedzenie: „w pierwszym skoroszycie, dla każdego arkusza, dla każdego wiersza, podaj mi pierwszą wartość / kolumnę”.
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]
Ale teraz dzięki zaawansowanemu indeksowaniu możemy myśleć o tym, x[(0,0,0),:,:,y]że „w pierwszym skoroszycie, dla każdego arkusza, dla każdego wiersza podaj mi ywartość th / kolumnę. Ok, teraz zrób to dla każdej wartości 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]]])
To, że wariuje, to to, że numpy będzie nadawać, aby pasowało do zewnętrznych wymiarów tablicy indeksów. Więc jeśli chcesz wykonać tę samą operację jak powyżej, ale ZARÓWNO dla „skoroszytów programu Excel”, nie musisz zapętlać i łączyć. Możesz po prostu przekazać tablicę do pierwszego wymiaru, ale MUSI mieć zgodny kształt.
Przekazywanie liczby całkowitej zostaje przekazane do y.shape == (3,). Jeśli chcesz przekazać tablicę jako pierwszy indeks, tylko ostatni wymiar tablicy musi być zgodny y.shape. To znaczy ostatni wymiar pierwszego indeksu musi wynosić 3 lub 1.
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)
Znaleziono krótkie wyjaśnienie w dokumentacji: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing
Edytować:
Z pierwotnego pytania, aby uzyskać linijkę żądanego subplikowania, możesz użyć x[0][:,:,y]:
x[0][:,:,y].shape
# returns
(2, 50, 3)
Jeśli jednak próbujesz przypisać do tych podsieci, musisz bardzo uważać, patrząc na widok pamięci współdzielonej oryginalnej tablicy. W przeciwnym razie przypisanie nie będzie do oryginalnej tablicy, ale do kopii.
Pamięć współdzielona występuje tylko wtedy, gdy używasz liczby całkowitej lub wycinka do podzestawu tablicy, tj . x[:,0:3,:,:]Lub x[0,:,:,1:-1].
np.shares_memory(x, x[0])
# returns:
True
np.shares_memory(x, x[:,:,:,y])
# returns:
False
Zarówno w twoim pierwotnym pytaniu, jak i moim przykładzie, ynie jest ani int, ani plasterek, więc zawsze kończy się przypisaniem do kopii oryginału.
ALE! Ze względu na swoją tablicę ymożna wyrazić jako plaster, ty CAN rzeczywiście uzyskać przypisywany widok macierzy poprzez:
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
Tutaj używamy wycinka, 0:21:10aby pobrać każdy indeks, który byłby w środku range(0,21,10). Musimy użyć, 21a nie 20dlatego, że punkt zatrzymania jest wykluczony z wycinka, tak jak w rangefunkcji.
Zasadniczo, jeśli możesz skonstruować plasterek, który pasuje do twoich kryteriów subplikowania, możesz wykonać przypisanie.