scipy 如何在稀疏矩阵中查找零元素

368yc8dk  于 2023-03-08  发布在  其他
关注(0)|答案(3)|浏览(123)

我知道scipy.sparse.find(A)返回3个数组I、J、V,每个数组分别包含行、列和非零元素的值。
我想要的是一种方法,可以对所有零元素做同样的事情(除了V数组),而不必迭代矩阵,因为它太大了。

z0qdvdin

z0qdvdin1#

创建一个稀疏度为10%的小稀疏矩阵:

In [1]: from scipy import sparse
In [2]: M = sparse.random(10,10,.1)
In [3]: M
Out[3]: 
<10x10 sparse matrix of type '<class 'numpy.float64'>'
    with 10 stored elements in COOrdinate format>

10个非零值:

In [5]: sparse.find(M)
Out[5]: 
(array([6, 4, 1, 2, 3, 0, 1, 6, 9, 6], dtype=int32),
 array([1, 2, 3, 3, 3, 4, 4, 4, 5, 8], dtype=int32),
 array([ 0.91828586,  0.29763717,  0.12771201,  0.24986069,  0.14674883,
         0.56018409,  0.28643427,  0.11654358,  0.8784731 ,  0.13253971]))

如果在矩阵的100个元素中,有10个非零,那么有90个元素为零,你真的想要所有这些元素的索引吗?
wherenonzero在稠密等价物上给出相同的指数:

In [6]: A = M.A # dense
In [7]: np.where(A)
Out[7]: 
(array([0, 1, 1, 2, 3, 4, 6, 6, 6, 9], dtype=int32),
 array([4, 3, 4, 3, 3, 2, 1, 4, 8, 5], dtype=int32))

以及90个零值的指数:

In [8]: np.where(A==0)
Out[8]: 
(array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5,
        5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9], dtype=int32),
 array([0, 1, 2, 3, 5, 6, 7, 8, 9, 0, 1, 2, 5, 6, 7, 8, 9, 0, 1, 2, 4, 5, 6,
        7, 8, 9, 0, 1, 2, 4, 5, 6, 7, 8, 9, 0, 1, 3, 4, 5, 6, 7, 8, 9, 0, 1,
        2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 3, 5, 6, 7, 9, 0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9], dtype=int32))

这是2个shape(90,)数组,180个整数,而不是密集数组本身的100个值。如果稀疏矩阵太大而无法转换为密集矩阵,那么它将太大而无法生成所有的零索引(假设合理的稀疏性)。
print(M)显示了与find相同的三元组,coo的属性也给予了非零索引:

In [13]: M.row
Out[13]: array([6, 6, 3, 4, 1, 6, 9, 2, 1, 0], dtype=int32)
In [14]: M.col
Out[14]: array([1, 4, 3, 2, 3, 8, 5, 3, 4, 4], dtype=int32)

(有时,矩阵的操作可以将值设置为0,而不会将其从属性中移除。因此,find/nonzero需要额外的步骤来移除这些值(如果有的话)。)
我们也可以将find应用于M==0-但是稀疏会给予我们一个警告。

In [15]: sparse.find(M==0)
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:213: SparseEfficiencyWarning: Comparing a sparse matrix with 0 using == is inefficient, try using != instead.
  ", try using != instead.", SparseEfficiencyWarning)

这和我之前警告过的是一样的--这个集合太大了。结果数组和Out[8]中的一样。

ql3eal8s

ql3eal8s2#

下面是我找到零值索引的解决方案:

from scipy.sparse import csr_matrix
csrm_reversed=sparse.csr_matrix((csrm.A==0)*1)
csrm_reversed.nonzero()

例如:

from scipy.sparse import csr_matrix
csrm = csr_matrix([[1,2,0],[0,0,3],[4,0,5]])
csrm.nonzero()

你会得到非零的索引:

(array([0, 0, 1, 2, 2], dtype=int32), array([0, 1, 2, 0, 2], dtype=int32))

然后找到零索引:

csrm_reversed=sparse.csr_matrix((csrm.A==0)*1)
csrm_reversed.nonzero()

您将获得:

(array([0, 1, 1, 2], dtype=int32), array([2, 0, 1, 1], dtype=int32))

矩阵的密集格式为:

[[1, 2, 0],
[0, 0, 3],
[4, 0, 5]]
rqmkfv5c

rqmkfv5c3#

假设您有一个scipy稀疏数组并导入了find

from itertools import product
I, J, _= find(your_sparse_array)
nonzero = zip(I, J)
nrows, ncols = your_sparse_array.shape
for a, b in product(range(nrows), range(ncols)):
    if (a,b) not in nonzero: print(a, b)

相关问题