¿Cómo editar celdas en una matriz dispersa usando scipy?

Estoy tratando de manipular algunos datos en una matriz dispersa. Una vez que he creado uno, ¿cómo agrego / altero / actualizo los valores en él? Esto parece muy básico, pero no puedo encontrarlo en la documentación de las clases de matriz dispersa o en la web. Creo que me falta algo crucial.

Este es mi bash fallido de hacerlo de la misma manera que lo haría con una matriz normal.

>>> from scipy.sparse import bsr_matrix >>> A = bsr_matrix((10,10)) >>> A[5][7] = 6 Traceback (most recent call last): File "", line 1, in  A[5][7] = 6 File "C:\Python27\lib\site-packages\scipy\sparse\bsr.py", line 296, in __getitem__ raise NotImplementedError NotImplementedError 

Existen varios formatos de matriz dispersa. Algunos son más adecuados para la indexación. Uno que lo ha implementado es lil_matrix .

 Al = A.tolil() Al[5,7] = 6 # the normal 2d matrix indexing notation print Al print Al.A # aka Al.todense() A1 = Al.tobsr() # if it must be in bsr format 

La documentación para cada formato sugiere en qué es bueno y dónde está mal. Pero no tiene una lista clara de cuáles tienen qué operaciones definidas.

 Advantages of the LIL format supports flexible slicing changes to the matrix sparsity structure are efficient ... Intended Usage LIL is a convenient format for constructing sparse matrices ... 

dok_matrix también implementa la indexación.

La estructura de datos subyacente para coo_matrix es fácil de entender. Esencialmente son los parámetros para coo_matrix((data, (i, j)), [shape=(M, N)]) definición. Para crear la misma matriz puedes usar:

 sparse.coo_matrix(([6],([5],[7])), shape=(10,10)) 

Si tiene más asignaciones, construye data más grandes, i , j listas (o arreglos 1d), y cuando termine de construir la matriz dispersa.

La documentación para bsr se encuentra aquí en bsr matrix y para csr se encuentra en csr matrix . Podría valer la pena entender el csr antes de pasar al bsr. La única diferencia es que bsr tiene entradas que son matrices en sí mismas, mientras que la unidad básica en un csr es un escalar.

No sé si hay formas muy fáciles de manipular las matrices una vez que se crean, pero aquí hay algunos ejemplos de lo que estás tratando de hacer,

 import numpy as np from scipy.sparse import bsr_matrix, csr_matrix row = np.array( [5] ) col = np.array( [7] ) data = np.array( [6] ) A = csr_matrix( (data,(row,col)) ) 

Esta es una syntax sencilla en la que usted lista todos los datos que desea en la matriz en los data la matriz y luego especifica dónde deben ir esos datos usando row y col . Tenga en cuenta que esto hará que las dimensiones de la matriz sean lo suficientemente grandes para mantener el elemento en la fila y columna más grandes (en este caso, una matriz de 6×8). Puede ver la matriz en forma estándar utilizando el método todense() .

 A.todense() 

Sin embargo, no puede manipular la matriz sobre la marcha utilizando este patrón. Lo que puedes hacer es modificar la representación de scipy nativa de la matriz. Esto involucra 3 atributos, indices , data y data . Para empezar, podemos examinar el valor de estos atributos para la matriz que ya hemos creado.

 >>> print A.data array([6]) >>> print A.indices array([7], dtype=int32) >>> print A.indptr array([0, 0, 0, 0, 0, 0, 1], dtype=int32) 

data son lo mismo que antes, una matriz de valores de 1 día que queremos en la matriz. La diferencia es que la posición de estos datos ahora se especifica mediante indices e indptr lugar de row y col . indices son bastante directos. Es simplemente una lista de la columna en la que se encuentra cada entrada de datos. Siempre tendrá el mismo tamaño y la matriz de data . indptr es un poco más complicado Le permite a la estructura de datos saber en qué fila está cada entrada de datos. Para citar de los documentos,

los índices de columna para la fila i se almacenan en indices[indptr[i]:indptr[i+1]]

A partir de esta definición, podemos ver que el tamaño de indptr siempre será el número de filas en la matriz + 1. Se tarda un poco en acostumbrarse, pero trabajar con los valores de cada fila le dará algo de intuición. Tenga en cuenta que todas las entradas son cero hasta la última. Eso significa que los índices de columna para las filas i=0-4 se almacenarán en indices[0:0] es decir, la matriz vacía. Esto se debe a que estas filas son todas ceros. Finalmente, en la última fila, i=5 obtenemos indices[0:1]=7 que nos dice que los datos de entrada de data[0:1] están en la fila 5, columna 7.

Ahora, supongamos que quisiéramos agregar el valor 10 en la fila 4 de la fila 4. Primero lo colocamos en el atributo de data ,

 A.data = np.array( [10,6] ) 

A continuación, actualizamos los indices para indicar que estará la columna 10,

 A.indices = np.array( [4,7], dtype=np.int32 ) 

y finalmente indicamos en qué fila estará modificando indptr

 A.indptr = np.array( [0,0,0,1,1,1,2], dtype=np.int32 ) 

Es importante que haga el tipo de datos de los indices e indptr np.int32 . Una forma de visualizar lo que está ocurriendo en indptr es que el cambio en los números se produce al pasar de i a i+1 de una fila que tiene datos. También tenga en cuenta que matrices como estas se pueden usar para construir matrices dispersas

 B = csr_matrix( (data,indices,indptr) ) 

Sería bueno si fuera tan fácil como simplemente indexar en la matriz como lo intentó, pero la implementación aún no está ahí. Eso debería ser suficiente para que comiences al menos.