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_array
per 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 _x
non è necessaria la ripetizione, (5,4); (5,1) è sufficiente.
La trasmissione fa una ripetizione virtuale. Questo può essere illustrato con la broadcast_to
funzione:
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 0
passi che si ripetono senza fare copie. as_strided
è la stride_tricks
funzione 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]]])