2012-05-19 23 views
10

¿Cuál es la mejor manera de eliminar columnas de una matriz dispersa que solo contiene ceros? Tengo una matriz que he creado y lleno de datos:¿Cómo eliminar eficientemente columnas de una matriz dispersa que solo contiene ceros?

matrix = sp.sparse.lil_matrix((100, 100)) 

ahora deseo para eliminar los últimos 20 ~ columnas que sólo contienen datos cero. ¿Cómo puedo hacer esto?

+3

¿Estás comprometido a utilizar lil_matrix? De acuerdo con los documentos scipy, no es eficiente para el corte de columnas; en su lugar, podría considerar csc_matrix. Ver: http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.lil_matrix.html y http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse. csc_matrix.html –

+0

Gracias por la ayuda. Sí, csr o csc también está bien. – turtle

+0

@turtle ¿Respondió esto a tu pregunta? – gabe

Respuesta

8

Si esto fuera sólo una matriz numpy, X, entonces se podría decir X!=0 lo que le daría una matriz booleana de la misma forma que X y entonces se podría índice X con la matriz booleana, es decir non_zero_entries = X[X!=0]

Pero esto es una matriz dispersa que no soporta la indexación booleano y también no le dará lo que quiere si intenta X!=0 - sólo se devuelve un canto le valor booleano que parece devolver verdadero solo si son exactamente la misma matriz (en memoria).

Lo que quiere es el método nonzero de numpy.

import numpy as np 
from scipy import sparse 

X = sparse.lil_matrix((100,100)) # some sparse matrix 
X[1,17] = 1 
X[17,17] = 1 
indices = np.nonzero(X) # a tuple of two arrays: 0th is row indices, 1st is cols 
X.tocsc()[indices] # this just gives you the array of all non-zero entries 

Si solo desea las columnas completas donde hay entradas distintas de cero, simplemente tome la 1ra de los índices. Salvo que usted necesita para tener en cuenta los índices repetidos (si hay más de uno entradas de una columna):

columns_non_unique = indices[1] 
unique_columns = sorted(set(columns_non_unique)) 
X.tocsc()[:,unique_columns] 
+3

Utilicé lo siguiente para extraer solo las columnas con entradas distintas de cero: 'matriz [:, np.unique (alldata.nonzero() [1])]' – canzar

+0

Eso es bueno y compacto. Más o menos lo mismo, excepto que usas numpy's unique en lugar de 'sorted (set (columns))'. – gabe

+1

para ser claros, la mayoría de las matrices dispersas tienen un método '.nonzero' que funciona de la misma manera, y mucho más rápido que' np.nonzero (sparse_matrix) '. Respuesta útil, no obstante. –

1

Esto se parece a la forma, aunque no está idealmente eficiente:

matrix = matrix[0:100,0:80] 
+0

Desafortunadamente, el número de columnas cero no siempre es fijo. Necesito una forma de hacer esto de forma que si hubiera 35 columnas cero o 10 columnas cero, el programa aún funcionaría. – turtle

0

También se puede utilizar scipy.sparse.find() para obtener las ubicaciones de todos los elementos no nulos en la matriz dispersa.

La entrada [1] en el valor devuelto es una matriz numpy de números de columna. Tomar los valores únicos de esta matriz proporciona los índices de las columnas distintas de cero. Subconjunto de la matriz dispersa original por estas columnas nos da las columnas distintas de cero.

x[:,np.unique(sparse.find(x)[1])] 

Uno puede extender esto para encontrar columnas con al menos n entradas:

idx = np.unique(sparse.find(x)[1], return_counts=True) 
x[:, idx[0][idx[1] > n]] 
Cuestiones relacionadas