¿Cómo puedo eliminar una columna de una matriz dispersa de manera eficiente?

Si estoy utilizando el formato sparse.lil_matrix, ¿cómo puedo eliminar una columna de la matriz de manera fácil y eficiente?

He estado queriendo esto yo mismo y, en verdad, todavía no hay una gran forma de hacerlo. Aquí hay una manera de hacerlo. Elegí hacer una subclase de lil_matrix y agregar la función remove_col. Si lo desea, puede agregar la función removecol a la clase lil_matrix en su archivo lib/site-packages/scipy/sparse/lil.py Aquí está el código:

 from scipy import sparse from bisect import bisect_left class lil2(sparse.lil_matrix): def removecol(self,j): if j < 0: j += self.shape[1] if j < 0 or j >= self.shape[1]: raise IndexError('column index out of bounds') rows = self.rows data = self.data for i in xrange(self.shape[0]): pos = bisect_left(rows[i], j) if pos == len(rows[i]): continue elif rows[i][pos] == j: rows[i].pop(pos) data[i].pop(pos) if pos == len(rows[i]): continue for pos2 in xrange(pos,len(rows[i])): rows[i][pos2] -= 1 self._shape = (self._shape[0],self._shape[1]-1) 

Lo he probado y no veo ningún error. Ciertamente pienso que es mejor que cortar la columna, lo que crea una nueva matriz, que yo sepa.

Decidí hacer una función de removerow también, pero no creo que sea tan bueno como removecol. Estoy limitado por no poder eliminar una fila de un ndarray de la forma que quisiera. Aquí está el removerow que se puede agregar a la clase anterior

  def removerow(self,i): if i < 0: i += self.shape[0] if i < 0 or i >= self.shape[0]: raise IndexError('row index out of bounds') self.rows = numpy.delete(self.rows,i,0) self.data = numpy.delete(self.data,i,0) self._shape = (self._shape[0]-1,self.shape[1]) 

Tal vez debería enviar estas funciones al repository de Scipy.

Mucho más simple y más rápido. Puede que ni siquiera necesite la conversión a csr, pero estoy seguro de que funciona con matrices dispersas de csr y la conversión entre ellas no debería ser un problema.

 from scipy import sparse x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list]) 

Para una matriz de csr dispersa (X) y una lista de índices para soltar (index_to_drop):

 to_keep = list(set(xrange(X.shape[1]))-set(index_to_drop)) new_X = X[:,to_keep] 

Es fácil convertir lil_matrices a csr_matrices. Compruebe tocsr () en la documentación de lil_matrix

Sin embargo, tenga en cuenta que pasar de las matrices csr a lil usando tolil () es costoso. Por lo tanto, esta opción es buena cuando no necesita tener su matriz en formato lil.

Soy nuevo en Python, así que mi respuesta probablemente sea incorrecta, pero me preguntaba por qué algo como lo siguiente no será eficiente.

Digamos que lil_matrix se llama mat y que desea eliminar la i-columna:

 mat=hstack( [ mat[:,0:i] , mat[:,i+1:] ] ) 

Ahora la matriz se convertirá en coo_matrix después de eso, pero puedes volver a lil_matrix.

Ok, entiendo que esto tendrá que crear las dos matrices dentro del hstack antes de hacer la asignación a la variable mat, por lo que sería como tener la matriz original más una más al mismo tiempo, pero supongo que si la dispersión es lo suficientemente grande entonces creo que no debería haber problemas de memoria (ya que la memoria (y el tiempo) es la razón principal del uso de matrices dispersas).

 def removecols(W, col_list): if min(col_list) = W.shape[1]: raise IndexError('column index out of bounds') rows = W.rows data = W.data for i in xrange(M.shape[0]): for j in col_list: pos = bisect_left(rows[i], j) if pos == len(rows[i]): continue elif rows[i][pos] == j: rows[i].pop(pos) data[i].pop(pos) if pos == len(rows[i]): continue for pos2 in xrange(pos,len(rows[i])): rows[i][pos2] -= 1 W._shape = (W._shape[0], W._shape[1]-len(col_list)) return W 

Solo reescribió su código para trabajar con col_list como entrada, tal vez esto sea útil para alguien.

Al observar las notas para cada matriz dispersa, específicamente en nuestro caso es csc matrix, tiene las siguientes ventajas que se enumeran en la documentación [1]

  • operaciones aritméticas eficientes CSC + CSC, CSC * CSC, etc.
  • corte de columna eficiente
  • productos vectoriales de matriz rápida (CSR, BSR puede ser más rápido)

Si tiene los índices de columna que desea eliminar, simplemente utilice el corte. Para eliminar filas use la matriz csr ya que es eficiente en el corte de filas