Come posso ottenere elementi dalla matrice 3D utilizzando indici specificati in numpy?
- Ho una matrice 3D, nell'esempio sotto è una matrice (5, 4, 2):
data_matrix - Ho un altro array di indici di forma (5, 4) in cui ogni riga di array rappresenta la posizione dell'elemento:
indx_array
Non so come posso ottenere il file required_output. Sto cercando di organizzare (1,2) elementi di ogni riga in base aindx_array
Non voglio usare i cicli for!
data_matrix = np.array([
[[0, 1], [2, 3], [4, 5], [6, 7]],
[[8, 9], [10, 11], [12, 13], [14, 15]],
[[16, 17], [18, 19], [20, 21], [22, 23]],
[[24, 25], [26, 27], [28, 29], [30, 31]],
[[32, 33], [34, 35], [36, 37], [38, 39]]
])
indx_array = np.array([[3,2,1,0], [0,1,2,3], [1,0,3,2], [0,3,1,2], [1,2,3,0]])
# I want following result:
required_output = [
[[6, 7], [4, 5], [2, 3], [0, 1]]
[[8, 9], [10, 11], [12, 13], [14, 15]]
[[18, 19], [16, 17], [22, 23], [20, 21]]
[[24, 25], [30, 31], [26, 27], [28, 29]]
[[34, 35], [36, 37], [38, 39], [32, 33]]
]
EDIT: aggiornato il indx_arrayper illustrare meglio la situazione.
Risposte
- Numpy: indicizzazione
- Numpy: indicizzazione di array multidimensionali
In [637]: data_matrix.shape
Out[637]: (5, 4, 2)
In [638]: indx_array.shape
Out[638]: (5, 4)
È necessaria un'indicizzazione avanzata sulle prime 2 dimensioni. La matrice della prima dimensione deve essere trasmessa con la seconda (5,4). Per farlo faccio un (5,1) arange:
In [639]: data_matrix[np.arange(5)[:,None], indx_array]
Out[639]:
array([[[ 6, 7],
[ 4, 5],
[ 2, 3],
[ 0, 1]],
[[ 8, 9],
[10, 11],
[12, 13],
[14, 15]],
[[18, 19],
[16, 17],
[22, 23],
[20, 21]],
[[24, 25],
[30, 31],
[26, 27],
[28, 29]],
[[34, 35],
[36, 37],
[38, 39],
[32, 33]]])
Confronta il mio indice (5,1) con quello accettato _x(che è (5,4) sfilato):
In [640]: np.arange(5)[:,None]
Out[640]:
array([[0],
[1],
[2],
[3],
[4]])
In [641]: _x = np.repeat(np.arange(indx_array.shape[0]),indx_array.shape[1])
In [643]: _x
Out[643]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4])
Con la trasmissione _xnon è necessaria la ripetizione, (5,4); (5,1) è sufficiente.
La trasmissione fa una ripetizione virtuale. Questo può essere illustrato con la broadcast_tofunzione:
In [648]: np.broadcast_to(np.arange(5)[:,None],(5,4))
Out[648]:
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4]])
In [649]: _.strides
Out[649]: (8, 0)
Sono quei 0passi che si ripetono senza fare copie. as_stridedè la stride_tricksfunzione più utile , specialmente quando si fanno cose come spostare le finestre. Di solito lasciamo che la trasmissione automatica faccia il lavoro senza preoccuparci troppo del come.
Può essere fatto con un po 'di mano dell'array index.
import numpy as np
_x = np.repeat(np.arange(indx_array.shape[0]),indx_array.shape[1])
_y = indx_array.ravel()
output = data_matrix[_x, _y].reshape(data_matrix.shape)
che si traduce nell'array numpy previsto
array([[[ 6, 7],
[ 4, 5],
[ 2, 3],
[ 0, 1]],
[[ 8, 9],
[10, 11],
[12, 13],
[14, 15]],
[[18, 19],
[16, 17],
[22, 23],
[20, 21]],
[[24, 25],
[30, 31],
[26, 27],
[28, 29]],
[[34, 35],
[36, 37],
[38, 39],
[32, 33]]])