¿Ver en una matriz numpy?

90

Tengo una numpymatriz 2D . ¿Hay alguna forma de crear una vista que incluya las primeras kfilas y todas las columnas?

El punto es evitar copiar los datos subyacentes (la matriz es tan grande que no es posible realizar copias parciales).

NPE
fuente

Respuestas:

226

Claro, simplemente indexe como lo haría normalmente. Por ejemplo, y = x[:k, :] esto devolverá una vista a la matriz original. No se copiará ningún dato y las actualizaciones realizadas yse reflejarán en xy viceversa.


Editar:

Normalmente trabajo con matrices 3D de> 10GB de uint8, así que me preocupo mucho por esto ... Numpy puede ser muy eficiente en la gestión de la memoria si tiene en cuenta algunas cosas. A continuación, se ofrecen algunos consejos para evitar realizar copias de matrices en la memoria:

Uso +=, -=, *=, etc, para evitar hacer una copia de la matriz. Por ejemplo x += 10, modificará la matriz en su lugar, mientras x = x + 10que hará una copia y la modificará. (también, eche un vistazo a numexpr )

Si desea hacer una copia con x = x + 10, tenga en cuenta que x = x + 10.0hará que se actualice xautomáticamente a una matriz de punto flotante, si no lo estaba ya. Sin embargo, x += 10.0donde xes una matriz de enteros, hará 10.0que se reduzca a un int de la misma precisión que la matriz.

Además, muchas funciones numpy toman un outparámetro, por lo que puede hacer cosas como np.abs(x, x)tomar el valor absoluto de xin situ.


Como segunda edición, aquí hay algunos consejos más sobre vistas frente a copias con matrices numpy:

A diferencia de las listas de Python, y = x[:]no devuelve una copia, devuelve una vista. Si desea una copia (que, por supuesto, duplicará la cantidad de memoria que está usando) usey = x.copy()

A menudo oirá hablar de "indexación elegante" de matrices numpy. Usar una lista (o matriz de números enteros) como índice es una "indexación elegante". Puede ser muy útil, pero copia los datos.

Como ejemplo de esto: y = x[[0, 1, 2], :]devuelve una copia, mientras y = x[:3,:]que devolvería una vista.

Sin embargo, incluso una indexación realmente loca como x[4:100:5, :-10:-1, None]es una indexación "normal" y devolverá una vista, así que no tenga miedo de usar todo tipo de trucos de corte en matrices grandes.

x.astype(<dtype>)devolverá una copia de los datos como el nuevo tipo, mientras x.view(<dtype>)que devolverá una vista.

Sin embargo, tenga cuidado con esto ... Es extremadamente poderoso y útil, pero debe comprender cómo se almacenan los datos subyacentes en la memoria. Si tiene una matriz de flotantes y los ve como ints, (o viceversa) numpy interpretará los bits subyacentes de la matriz como ints.

Por ejemplo, esto significa que 1.0como un flotante de 64 bits en un sistema little-endian se verá 4607182418800017408como un int de 64 bits, y una matriz de [ 0, 0, 0, 0, 0, 0, 240, 63]si se verá como un uint8. Sin embargo, esto es realmente bueno cuando necesita hacer cambios de bits de algún tipo en matrices grandes ... Tiene un control de bajo nivel sobre cómo se interpreta el búfer de memoria.

Joe Kington
fuente
¡Gracias por los buenos consejos! Estaba leyendo la guía del usuario de Numpy y confundido por qué se x[np.array([1, 1, 3, 1])] += 1modificó x. ¡Ahora lo tengo!
tnq177
buenos consejos! Tengo otra pregunta. ¿Cómo demostrar que numpy no genera una copia sino solo una vista? id de python () parece incapaz de esto.
wuhaochi
3
@wuhaochi Si bes una vista de a, entonces b.base is aserá True. Una copia (de cualquier matriz) siempre tendráarr_copy.base is None
Jürg Merlin Spaak