Quiero cortar una matriz NumPy nxn. Quiero extraer una selección arbitraria de m filas y columnas de esa matriz (es decir, sin ningún patrón en el número de filas / columnas), convirtiéndola en una nueva matriz mxm. Para este ejemplo, digamos que la matriz es 4x4 y quiero extraer una matriz de 2x2.
Aquí está nuestra matriz:
from numpy import *
x = range(16)
x = reshape(x,(4,4))
print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
La línea y las columnas para eliminar son las mismas. El caso más fácil es cuando quiero extraer una submatriz de 2x2 que está al principio o al final, es decir:
In [33]: x[0:2,0:2]
Out[33]:
array([[0, 1],
[4, 5]])
In [34]: x[2:,2:]
Out[34]:
array([[10, 11],
[14, 15]])
Pero, ¿qué sucede si necesito eliminar otra mezcla de filas / columnas? ¿Qué sucede si necesito eliminar la primera y tercera línea / fila, extrayendo así la submatriz [[5,7],[13,15]]
? Puede haber cualquier composición de filas / líneas. Leí en alguna parte que solo necesito indexar mi matriz usando matrices / listas de índices tanto para filas como para columnas, pero eso no parece funcionar:
In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])
Encontré una forma, que es:
In [61]: x[[1,3]][:,[1,3]]
Out[61]:
array([[ 5, 7],
[13, 15]])
El primer problema con esto es que apenas es legible, aunque puedo vivir con eso. Si alguien tiene una mejor solución, ciertamente me gustaría escucharla.
Otra cosa es que leí en un foro que indexar matrices con matrices obliga a NumPy a hacer una copia de la matriz deseada, por lo tanto, cuando se trata con matrices grandes, esto podría convertirse en un problema. ¿Por qué es así / cómo funciona este mecanismo?
x[[[1],[3]],[1,3]]
crea solo una nueva matriz, mientras quex[[1,3],:][:,[1,3]]
copia dos veces, así que use la primera.No creo que
x[[1,3]][:,[1,3]]
sea difícil de leer. Si desea ser más claro en su intención, puede hacer lo siguiente:No soy un experto en segmentación pero, por lo general, si intentas dividir en una matriz y los valores son continuos, obtienes una vista donde se cambia el valor de zancada.
Por ejemplo, en sus entradas 33 y 34, aunque obtiene una matriz de 2x2, el paso es 4. Por lo tanto, cuando indexa la siguiente fila, el puntero se mueve a la posición correcta en la memoria.
Claramente, este mecanismo no funciona bien en el caso de una serie de índices. Por lo tanto, numpy tendrá que hacer la copia. Después de todo, muchas otras funciones matemáticas de matriz dependen del tamaño, el paso y la asignación continua de memoria.
fuente
Si desea omitir todas las filas y columnas, puede hacerlo con un corte básico:
Esto devuelve una vista, no una copia de su matriz.
while
z=x[(1,3),:][:,(1,3)]
usa indexación avanzada y, por lo tanto, devuelve una copia:Tenga en cuenta que no
x
ha cambiado:Si desea seleccionar filas y columnas arbitrarias, entonces no puede usar la división básica. Tendrás que usar indexación avanzada, usando algo como
x[rows,:][:,columns]
, dónderows
ycolumns
son secuencias. Esto, por supuesto, le dará una copia, no una vista, de su matriz original. Esto es como uno debería esperar, ya que una matriz numpy usa memoria contigua (con zancadas constantes), y no habría forma de generar una vista con filas y columnas arbitrarias (ya que eso requeriría zancadas no constantes).fuente
Con numpy, puede pasar un segmento para cada componente del índice; por lo tanto, su
x[0:2,0:2]
ejemplo anterior funciona.Si solo desea omitir columnas o filas de manera uniforme, puede pasar sectores con tres componentes (es decir, inicio, detención, paso).
Nuevamente, para su ejemplo anterior:
Que es básicamente: cortar en la primera dimensión, con inicio en el índice 1, parar cuando el índice es igual o mayor que 4, y agregar 2 al índice en cada pasada. Lo mismo para la segunda dimensión. De nuevo: esto solo funciona para pasos constantes.
La sintaxis que tiene que hacer internamente es algo muy diferente: lo que
x[[1,3]][:,[1,3]]
realmente hace es crear una nueva matriz que incluya solo las filas 1 y 3 de la matriz original (hecha con lax[[1,3]]
parte), y luego volver a cortarla, creando una tercera matriz, incluyendo solo columnas 1 y 3 de la matriz anterior.fuente
Tengo una pregunta similar aquí: escribir en sub-ndarray de un ndarray de la manera más pitoniana. Python 2 .
Siguiendo la solución de la publicación anterior para su caso, la solución se ve así:
Un uso de ix_:
Cual es:
fuente
No estoy seguro de cuán eficiente es esto, pero puede usar range () para cortar en ambos ejes
fuente