scipy稀疏矩阵:删除所有元素为零的行

时间:2015-07-02 15:01:53

标签: python numpy scipy scikit-learn

我有一个稀疏矩阵,它是从sklearn tfidfVectorier转换而来的。我相信有些行是全零行。我想删除它们。但是,据我所知,现有的内置功能,例如, nonzero()和eliminate_zero(),关注零条目而不是行。

有没有简单的方法从稀疏矩阵中删除全零行?

实施例: 我现在拥有的(实际上是稀疏格式):

[ [0, 0, 0]
  [1, 0, 2]
  [0, 0, 1] ]

我想得到什么:

[ [1, 0, 2]
  [0, 0, 1] ]

3 个答案:

答案 0 :(得分:9)

切片+ getnnz()可以解决问题:

M = M[M.getnnz(1)>0]

直接在csr_array上投放。 您也可以删除所有0列而不更改格式:

M = M[:,M.getnnz(0)>0]

但是,如果你想删除两个,你需要

M = M[M.getnnz(1)>0][:,M.getnnz(0)>0] #GOOD

我不确定为什么但是

M = M[M.getnnz(1)>0, M.getnnz(0)>0] #BAD

不起作用。

答案 1 :(得分:4)

没有现成的功能,但编写自己的功能并不算太糟糕:

def remove_zero_rows(M):
  M = scipy.sparse.csr_matrix(M)

首先,将矩阵转换为CSR (compressed sparse row)格式。这很重要,因为CSR矩阵将其数据存储为(data, indices, indptr)的三倍,其中data保存非零值,indices存储列索引,indptr保存行索引信息。文档解释得更好:

  

第i行的列索引存储在   indices[indptr[i]:indptr[i+1]]及其对应的值   存储在data[indptr[i]:indptr[i+1]]

因此,要查找没有任何非零值的行,我们只需查看M.indptr的连续值。从上面继续我们的职能:

  num_nonzeros = np.diff(M.indptr)
  return M[num_nonzeros != 0]

CSR格式的第二个好处是切片行相对便宜,这简化了生成矩阵的创建。

答案 2 :(得分:1)

感谢您的回复,@ perimosocordiae

我自己找到另一种解决方案。我发布在这里以防将来有人可能需要它。

def remove_zero_rows(X)
    # X is a scipy sparse matrix. We want to remove all zero rows from it
    nonzero_row_indice, _ = X.nonzero()
    unique_nonzero_indice = numpy.unique(nonzero_row_indice)
    return X[unique_nonzero_indice]