Tengo una matriz dimensional (2 x 1 x 2 x 2 x 2):

array([[[[[ 7.,  9.],
          [10., 11.]],

         [[19., 18.],
          [20., 16.]]]],



       [[[[24.,  5.],
          [ 6., 10.]],

         [[18., 11.],
          [45., 12.]]]]])

Las dos últimas dimensiones son H (alto) y W (ancho) respectivamente. Ahora tengo dos matrices separadas con indexación a lo largo de H y W:

idx2=np.array([1, 1, 0, 1]) # index along H
idx3=np.array([1, 0, 0, 0]) # index along W

Por lo tanto, en términos de las dos últimas dimensiones, me gustaría extraer el elemento (1,1) de [[ 7.,9.],[10.,11.]], es decir, 11; y el elemento (1, 0) de [[19.,18.],[20.,16.]], es decir, 20, y así sucesivamente. El resultado final debe ser una (2 x 1 x 2) matriz :

array([[[11., 20.]],

       [[24., 45.]]])

Gracias por cualquier ayuda!

0
Sam-gege 5 oct. 2021 a las 11:24

3 respuestas

La mejor respuesta

Una posible forma de resolver esto usando una combinación de np.ravel_multi_index y np.take_along_axis.


Puede desentrañar los índices en las dos últimas dimensiones y usar np.take_along_axis en este eje de dimensión espacial aplanado h x w:

>>> flat_idx = (idx2*x.shape[-1]+idx3).reshape(*x.shape[:-2], 1)
>>> flat_idx 
array([[[[3],
         [2]]],


       [[[0],
         [2]]]])

Como alternativa, puede optar por utilizar el np.ravel_multi_index, pero es un poco más largo:

>>> flat_idx = np.ravel_multi_index((idx2, idx3), x.shape[-2:]).reshape(*x.shape[:-2], 1)

Luego, aplana las dos últimas dimensiones de x y reúne los índices:

>>> res = np.take_along_axis(x.reshape(*x.shape[:-2], -1), flat_idx, -1)
>>> res
array([[[[11.],
         [20.]]],


       [[[24.],
         [45.]]]])

En este punto será necesaria una remodelación:

>>> res.reshape(*x.shape[0:-2])
array([[[11., 20.]],

       [[24., 45.]]])

Si infieres las formas, con idx2 y idx3 esto se reduce a:

>>> flat_idx = (idx2*2+idx3).reshape(2, 1, 2, 1)
>>> res = np.take_along_axis(x.reshape(2, 1, 2, 4), flat_idx, -1)
>>> res.reshape((2, 1, 2))

El método anterior se puede utilizar para manejar un caso más general con idx2, idx3, idx4, ...

1
Ivan 5 oct. 2021 a las 09:16

Si tiene una matriz dimensional 2x1x2x2x2, array_name.

import numpy as np
array_name = np.array([[[[[ 7.,  9.],
                          [10., 11.]],
                         [[19., 18.],
                          [20., 16.]]]],
                       [[[[24.,  5.],
                          [ 6., 10.]],
                         [[18., 11.],
                          [45., 12.]]]]])

array_name[0] y array_name[1] son matrices dimensionales 1x2x2x2.

array_name[0].shape # (1, 2, 2, 2)

array_name[0][0] es una matriz dimensional 2x2x2.

array_name[0][0].shape # (2, 2, 2)

array_name[0][0][0] es una matriz dimensional de 2x2.

array_name[0][0][0].shape # (2, 2)

array_name[0][0][0][0] es una matriz bidimensional.

array_name[0][0][0][0].shape # (2,)

Para la matriz dada en la pregunta:

array_name[0][0][0][1][1] # 11.
array_name[0][0][1][1][0] # 20.
array_name[1][0][0][0][0] # 24.
array_name[1][0][1][1][0] # 45.

Este método es increíblemente detallado, por lo que en su lugar puede utilizar la indexación avanzada.

idx_0 = [0,0,1,1]
idx_2 = [0,1,0,1]
idx_3 = [1,1,0,1]
idx_4 = [1,0,0,0]

Los valores en cada una de las matrices idx_X se toman de los índices de matriz en el código detallado anterior y se utilizan para crear una única matriz de 4 elementos como tal.

array_name[idx_0, 0, idx_2, idx_3, idx_4]
# array([11., 20., 24., 45.])
0
Dan Nagle 5 oct. 2021 a las 09:10

Consulte indexación numpy:

idx0=np.array([0,0,1,1])
idx1=np.array([0,1,0,1])
array[idx0,0,idx1,idx2,idx3]

Otra forma más hacky: (he nombrado la matriz a en mi código)

np.diag(a[:,:,:,idx2,idx3].reshape((4,-1))) 

Tendría que reemplazar 4 por el producto de las otras dimensiones en el caso general.

0
kubatucka 5 oct. 2021 a las 09:34