Remodelar la matriz dispersa de manera eficiente, Python, SciPy 0.12

En otra publicación relacionada con el cambio de tamaño de una matriz dispersa en SciPy, la respuesta aceptada funciona cuando se agregan más filas o columnas, utilizando scipy.sparse.vstack o hstack , respectivamente. En SciPy 0.12, los métodos de reshape o set_shape aún no están implementados.

¿Existen algunas buenas prácticas sólidas para remodelar una matriz dispersa en SciPy 0.12? Sería bueno tener algunas comparaciones de tiempo.

A partir de SciPy 1.1.0 , los métodos de reshape y set_shape se han implementado para todos los tipos de matriz dispersa. Las firmas son lo que usted esperaría y son tan idénticas a los métodos equivalentes en NumPy como sea posible (por ejemplo, no puede cambiar la forma a un vector o tensor).

Firma:

 reshape(self, shape: Tuple[int, int], order: 'C'|'F' = 'C', copy: bool = False) -> spmatrix 

Ejemplo:

 >>> from scipy.sparse import csr_matrix >>> A = csr_matrix([[0,0,2,0], [0,1,0,3]]) >>> print(A) (0, 2) 2 (1, 1) 1 (1, 3) 3 >>> B = A.reshape((4,2)) >>> print(B) (1, 0) 2 (2, 1) 1 (3, 1) 3 >>> C = A.reshape((4,2), order='F') >>> print(C) (0, 1) 2 (3, 0) 1 (3, 1) 3 

Revelación completa: escribí las implementaciones.

No conozco ninguna buena práctica establecida, así que aquí hay una función de configuración bastante simple para una coo_matrix. Convierte su argumento en un coo_matrix, por lo que funcionará para otros formatos dispersos (pero devuelve un coo_matrix).

 from scipy.sparse import coo_matrix def reshape(a, shape): """Reshape the sparse matrix `a`. Returns a coo_matrix with shape `shape`. """ if not hasattr(shape, '__len__') or len(shape) != 2: raise ValueError('`shape` must be a sequence of two integers') c = a.tocoo() nrows, ncols = c.shape size = nrows * ncols new_size = shape[0] * shape[1] if new_size != size: raise ValueError('total size of new array must be unchanged') flat_indices = ncols * c.row + c.col new_row, new_col = divmod(flat_indices, shape[1]) b = coo_matrix((c.data, (new_row, new_col)), shape=shape) return b 

Ejemplo:

 In [43]: a = coo_matrix([[0,10,0,0],[0,0,0,0],[0,20,30,40]]) In [44]: aA Out[44]: array([[ 0, 10, 0, 0], [ 0, 0, 0, 0], [ 0, 20, 30, 40]]) In [45]: b = reshape(a, (2,6)) In [46]: bA Out[46]: array([[ 0, 10, 0, 0, 0, 0], [ 0, 0, 0, 20, 30, 40]]) 

Ahora, estoy seguro de que hay varios colaboradores regulares aquí que pueden aportar algo mejor (más rápido, más eficiente en memoria, menos llenado … 🙂

Tengo un ejemplo de trabajo para la matriz de CSR, pero no puedo garantizar que siempre funcione

aplanando la matriz A:

  indices = zeros_like(A.indices) indices[A.indptr[1:-1]] = A.shape[1] indices = cumsum( indices)+A.indices A_flat = sparse.csc_matrix((T_rot.data, indices,[0,size(A)]),shape=(prod(A.shape),1)) 

remodelando la matriz A

  indices = zeros_like(A.indices) indices[A.indptr[1:-1]] = A.shape[1] indices = cumsum( indices)+A.indices indices %= N*A.shape[1] indptr = r_[0, where(diff(indices)<0)[0]+1, size(A)] A_reshaped = sparse.csc_matrix((A.data, indices,indptr),shape=(N*A.shape[1],A.shape[0]/N ))