Tengo una matriz de valores por ejemplo
x = array([[[-0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. , 0. , 0. , 0. ], [ 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. , 0. , 0. ], [ 0. , 0. , 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. ], [ 0. , 0. , 0. , 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487]], [[-0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. , 0. , 0. , 0. ], [ 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. , 0. , 0. ], [ 0. , 0. , 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487, 0. ], [ 0. , 0. , 0. , 0. , -0.78867513, -0.21132487, 0. , 0.78867513, 0.21132487]]])
Quiero usar la indexación avanzada para extraer los valores distintos de cero. Conozco los índices de los valores distintos de cero por lo que
idx = array([[4, 3, 1, 0], [5, 4, 2, 1], [7, 6, 4, 3], [8, 7, 5, 4]])
El resultado deseado sería algo así como
x[idx] = array([[[-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487]], [[-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487], [-0.78867513, -0.21132487, 0.78867513, 0.21132487]]])
La matriz x
real es mucho más grande en la primera dimensión, pero la estructura distinta de cero siempre está indicada por idx
así que la necesito para transmitir a lo largo de la primera dimensión. es posible?
EDITAR: Para que quede claro x
largo de la primera dimensión contiene una lista anidada de 4 x 9
array. idx
luego tiene las entradas que no son cero fila por fila. Observe en la primera fila de ambas matrices anidadas 4 x 9
en x
que las entradas 4 3 1 0
son distintas de cero.
Prueba este:
x[:,np.arange(idx.shape[0])[:,None],idx]
Usando esta técnica, cada elemento en np.arange(idx.shape[0])[:,None]
(que tiene forma (idx.shape [0], 1) y por lo tanto es un vector de columna) se transmitirá con cada fila en idx Esto se utilizará para todas las entradas a lo largo del primer eje de x.
Intenté este forro para su problema y parece que hace el trabajo sin necesidad de idx
. Es posible que deba cambiar el parámetro en .reshape()
acuerdo con el tamaño de su problema.
np.array(filter(lambda x: x!=0, x.ravel())).reshape(-1, 4, 4)
Aplana la matriz, elimina los ceros y luego los vuelve a cambiar a la forma requerida.
Aquí hay otra versión que probablemente sea más eficiente, ya que no usa la función de filter
y en su lugar usa la indexación booleana para matrices numpy
y = x.ravel() z = y[y!=0].reshape(-1, 4, 4)
EDITAR:
Mientras jugaba con Numpy, descubrí otra forma de hacerlo.
x[x!=0].reshape(-1, 4, 4)
Y aquí está el rendimiento de los tres métodos:
10000 loops, best of 3: 21.2 µs per loop
100000 loops, best of 3: 2.42 µs per loop
100000 loops, best of 3: 1.97 µs per loop
OK, esto es un poco extraño, pero aquí va …
idxes = np.ones((x.shape[0], x.shape[1], 1), dtype=bool) * idx print x[np.array(x, dtype=bool)].reshape(idxes.shape)
Y, por supuesto, debes recordar escribir np.array
lugar de un array
.
¡Aclamaciones!
Y puede descargarse de la computación idx con lo siguiente:
y = x[np.array(x, dtype=bool)] print y.reshape(x.shape[0], x.shape[1], y.size/x.shape[0]/x.shape[1])
Con esto o las líneas de arriba, es el lanzamiento de los flotadores como bolas que proporciona una máscara que elimina los ceros.