【问题标题】:Sparse matrix: removal of rows if their sum is lower than X (Scipy)稀疏矩阵:如果行的总和低于 X (Scipy),则删除行
【发布时间】:2020-08-07 00:54:40
【问题描述】:

假设我有以下稀疏矩阵:

from scipy.sparse import coo_matrix
m = coo_matrix(([1,1,1,3,2], ([1,2,2,3,4],[1,1,2,3,3])))
print(m.toarray())

>>> array([[0, 0, 0, 0],
>>>       [0, 1, 0, 0],
>>>       [0, 1, 1, 0],
>>>       [0, 0, 0, 3],
>>>       [0, 0, 0, 2]])

我只想保留总和大于 1 的行。我认为以下方法可行。

csr = m.tocsr()
csr[(csr.sum(1) > 1)]

但它没有。相反,我必须对 numpy 数组进行转换(使用 squeeze):

csr = m.tocsr()
csr = csr[np.asarray(csr.sum(1) > 1).squeeze()]
csr.toarray()

所以,我得到了我想要的:

array([[0, 1, 1, 0],
       [0, 0, 0, 3],
       [0, 0, 0, 2]], dtype=int64)

有没有更直接的方法?

我知道有类似的答案,例如 在检查了this one之类的其他答案后,但在他们的情况下(使用M.getnnz(1)>0),该函数直接返回一个数组。

【问题讨论】:

  • 你可以使用 ravel,但我不认为更直接。
  • @DaniMesejo,不一样吗? csr[np.asarray(csr.sum(1) > 1).ravel()] 而不是 csr[np.asarray(csr.sum(1) > 1).squeeze()]。或者,你是什么意思? ravel() 效率更高吗?
  • 这应该可以工作:csr[np.ravel(csr.sum(1) > 1), :]

标签: python numpy scipy sparse-matrix


【解决方案1】:

看细节:

In [803]: m = sparse.csr_matrix(([1,1,1,3,2], ([1,2,2,3,4],[1,1,2,3,3])))                              
In [804]: m                                                                                            
Out[804]: 
<5x4 sparse matrix of type '<class 'numpy.longlong'>'
    with 5 stored elements in Compressed Sparse Row format>
In [805]: m.A                                                                                          
Out[805]: 
array([[0, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 1, 1, 0],
       [0, 0, 0, 3],
       [0, 0, 0, 2]], dtype=int64)
In [806]: m.sum(axis=1)                                                                                
Out[806]: 
matrix([[0],
        [1],
        [2],
        [3],
        [2]])

sum on ndarray 会减小尺寸(除非设置了 keepdims)。但是sparse 复制np.matrix,并保留尺寸。所以结果是一个 (5,1) 矩阵。

np.matrix 有一个array/ravel 步骤的缩写:

In [807]: m.sum(axis=1).A1                                                                             
Out[807]: array([0, 1, 2, 3, 2])

以及索引:

In [811]: m[m.sum(axis=1).A1>1,:]                                                                      
Out[811]: 
<3x4 sparse matrix of type '<class 'numpy.longlong'>'
    with 4 stored elements in Compressed Sparse Row format>
In [812]: _.A                                                                                          
Out[812]: 
array([[0, 1, 1, 0],
       [0, 0, 0, 3],
       [0, 0, 0, 2]], dtype=int64)

我在其他地方提到过csr 矩阵索引(通常)使用“提取矩阵”和矩阵乘法。考虑到数据的存储方式,这是稳健且合理的,但它不如密集数组索引那么快或强大。

有时我们通过作用于矩阵的基本属性dataindicesindptr 来提高速度。但这需要对这种表示有更多的了解,所以我不会在这里详细介绍。

【讨论】:

  • 查看细节是我找到解决方案的方式。我不知道.A1,但它相当于np.asarray(x).ravel(),正如here 所记录的那样。 squeeze()ravel() 类似,但只适用于一维矩阵,所以我想在避免编程错误的意义上更安全。我一直在寻找一种更直接的方法。而A1 就可以了。
  • A1 转换很便宜
  • +1,我刚刚注意到您还直接创建了csr_matrix。不是问题的一部分,但我的代码也有不必要的转换
猜你喜欢
  • 2017-01-15
  • 2016-10-29
  • 2017-07-02
  • 2016-12-21
  • 1970-01-01
  • 2015-09-20
  • 2020-09-24
  • 1970-01-01
  • 2014-10-15
相关资源
最近更新 更多