2012-07-09 8 views
9

Tanto en MATLAB como en Numpy, las matrices pueden indexarse ​​mediante matrices. Sin embargo, el comportamiento es diferente. Déjame explicar esto por un ejemplo.Indización de matriz similar a MATLAB con Numpy

MATLAB:

>> A = rand(5,5) 

A = 

    0.1622 0.6020 0.4505 0.8258 0.1067 
    0.7943 0.2630 0.0838 0.5383 0.9619 
    0.3112 0.6541 0.2290 0.9961 0.0046 
    0.5285 0.6892 0.9133 0.0782 0.7749 
    0.1656 0.7482 0.1524 0.4427 0.8173 

>> A([1,3,5],[1,3,5]) 

ans = 

    0.1622 0.4505 0.1067 
    0.3112 0.2290 0.0046 
    0.1656 0.1524 0.8173 

Numpy:

In [2]: A = arange(25).reshape((5,5)) 

In [3]: A 
Out[3]: 
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]]) 

In [6]: A[[0,2,4], [0,2,4]] 
Out[6]: array([ 0, 12, 24]) 

En palabras: MATLAB selecciona filas y columnas, NumPy "cremalleras" las dos matrices de índice y utiliza las tuplas para que apunte a las entradas.

¿Cómo puedo obtener el comportamiento de MATLAB con Numpy?

Respuesta

7

Usted puede hacer esto:

A[[0,2,4],:][:,[0,2,4]] 

que dará el resultado de MATLAB como desea.

Vale la pena ser conscientes de que, en lugar de forma inconsistente, si se utiliza rebanadas para la indexación a continuación, se obtienen resultados MATLAB sin que haya cualquier tales hackery:

>>> A[1:3,1:3] 
array([[ 6, 7], 
     [11,12]]) 

En numpy, a diferencia de MATLAB, 1:3 no es sólo una abreviatura para [1,2] o algo por el estilo. (En ese momento me siento obligado a mencionar algo que seguramente ya sabe, a saber, que pitón de 1:3 es un poco como [1,2] mientras que MATLAB es un poco como [1,2,3]:. El punto final de la derecha está incluido en MATLAB y excluidos en Python)

+3

Esto es realmente muy ineficiente. Requiere crear una matriz temporal en la memoria que puede ser bastante grande dependiendo del tamaño de las matrices con las que está trabajando. Hay varias formas más eficientes de hacerlo, incluido el uso de la función ix_ helper. –

+2

Sí, todo correcto. Por otro lado, la cosa construida por 'ix_' también es bastante grande, aunque temporal. Hice algunos experimentos de sincronización para una matriz de 5x5 como en la pregunta original, con los siguientes resultados. '[,:] [:,]' es aproximadamente un 25% más rápido que '[ix _()]', pero si usa los mismos índices cada vez que construye una matriz de indexación * una vez * con 'ix_' y la vuelve a usar es aproximadamente 10 veces más rápido, aunque, por supuesto, pagas un costo por el uso de la memoria. –

+2

np.ix_, en la mayoría de los casos, solo usa una cantidad trivial de memoria porque devuelve vistas de sus argumentos. También np.ix_ es una operación de tiempo constante, mientras que A [I1,:] [:, I2] es ~ n^2 tanto en tiempo como en uso de memoria. Pero si realmente necesitas un aumento del rendimiento del 25% en tu matriz 5x5, debes hacer lo que tienes que hacer. –

14

Usted puede utilizar la función auxiliar numpy.ix_ para obtener el comportamiento de Matlab:

from numpy import ix_ 
A[ ix_([0,2,4], [0,2,4]) ] 
1

la forma más eficiente de hacer esto con numpy es remodelar su matriz de índice para que coincida con los ejes que son la indexación es decir

In [103]: a=numpy.arange(100).reshape(10,10) 

In [104]: a 
Out[104]: 
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], 
    [40, 41, 42, 43, 44, 45, 46, 47, 48, 49], 
    [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]]) 

In [105]: x=numpy.array([3,6,9]) 

In [106]: y=numpy.array([2,7,8]) 

In [107]: a[x[:,numpy.newaxis],y[numpy.newaxis,:]] 
Out[107]: 
array([[32, 37, 38], 
     [62, 67, 68], 
     [92, 97, 98]]) 

normas de radiodifusión de numpy son de su amigo (y mucho mejor que MATLAB) ...

HTH

Cuestiones relacionadas