按轴汇总scipy矩阵中的非零值

时间:2019-12-14 19:40:57

标签: python numpy scipy sparse-matrix

我有这段代码总结了稀疏csr矩阵的每一行:

count_list = dtm.toarray().sum(axis=0)

如何代替总结每一行,就像每个非零值等于1? 我可以将所有值>0替换为1,然后使用与上面相同的代码。 我还可以遍历矩阵的每一行并使用Numpy的count_nonzero

count_list = [np.count_nonzero(v) for v in row.toarray() for row in dtm]

有没有更简单或更直接的方法(类似于第一个示例中的方法)?

2 个答案:

答案 0 :(得分:2)

In [1]: from scipy import sparse                                                
In [2]: M = sparse.random(10,10,.2, 'csr')                                      
In [3]: M                                                                       
Out[3]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>'
    with 20 stored elements in Compressed Sparse Row format>
In [4]: M.astype(bool)                                                          
Out[4]: 
<10x10 sparse matrix of type '<class 'numpy.bool_'>'
    with 20 stored elements in Compressed Sparse Row format>

In [6]: M.astype(bool).sum(axis=0)                                              
Out[6]: matrix([[0, 3, 4, 3, 1, 3, 1, 0, 2, 3]], dtype=int64)

将其与数组进行比较-转换为0/1整数

In [7]: M.astype(bool).astype(int).A                                            
Out[7]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 0, 0, 0, 0, 0, 1, 1],
       [0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
       [0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0, 0, 0, 0]])

对照矩阵nnz检查总数:

In [8]: M.astype(bool).sum(axis=0).sum()                                        
Out[8]: 20

对于axis=0,总和跨行,每列一个值。对于各列的总和(每行一个值),请使用axis=1)

In [13]: M.astype(bool).sum(axis=1)                                             
Out[13]: 
matrix([[0],
        [4],
        [2],
        [2],
        [3],
        [1],
        [4],
        [1],
        [1],
        [2]])

这是一个(n,1)密集矩阵。您可以使用A1来制作一维数组:M.astype(bool).sum(axis=1).A1

当矩阵不是正方形时,区别更容易看到。

count_nonzero可以对密集数组(但不能用于稀疏数组)执行相同操作:

In [15]: np.count_nonzero(M.A,axis=1)                                           
Out[15]: array([0, 4, 2, 2, 3, 1, 4, 1, 1, 2])

使用@fuglede's indptr方法:

In [18]: np.diff(M.indptr)                                                      
Out[18]: array([0, 4, 2, 2, 3, 1, 4, 1, 1, 2], dtype=int32)

答案 1 :(得分:1)

假设您没有明确的零,这是

count_list = dtm.indptr[1:] - dtm.indptr[:-1]

例如:

In [34]: dtm = scipy.sparse.random(1000, 1000, format='csr')                                    

In [35]: count_list_np = [np.count_nonzero(v) for row in dtm for v in row.toarray()]            

In [36]: count_list = dtm.indptr[1:] - dtm.indptr[:-1]                                          

In [37]: np.array_equal(count_list, count_list_np)                                              
Out[37]: True

如果您确实有明确的零,只需先使用eliminate_zeros将其删除:

dtm.eliminate_zeros()
count_list = dtm.indptr[1:] - dtm.indptr[:-1]