在Scipy中创建稀疏矩阵时覆盖而不是添加重复的三元组

2022-04-13 00:00:00 python scipy sparse-matrix

问题描述

在Scipy中,要从三重格式数据(行、列和数据数组)创建稀疏矩阵,默认行为是对所有重复项的数据值求和。我可以将此行为更改为覆盖(或不执行任何操作)吗?

例如:

import scipy.sparse as sparse

rows = [0, 0]
cols = [0, 0]
data = [1, 1]
S = sparse.coo_matrix((data, (rows, cols)))

此处,S.todense()等于matrix([[2]]),但我希望它是matrix([[1]])

在documentation of sparse.coo_matrix中,显示为

默认情况下,转换为CSR或CSC格式时,会复制(i,j) 参赛作品将汇总在一起。这有助于提高效率 有限元矩阵的构造等。

从该公式看,可能存在默认选项以外的其他选项。


解决方案

我在Scipy GitHub上看到了关于对此汇总进行更多控制的讨论,但我不知道有任何生产上的变化。正如文件显示的那样,对重复项求和是一个由来已久的传统。

创建时,coo矩阵不求和;它只是将参数分配给它的属性:

In [697]: S = sparse.coo_matrix((data, (rows, cols)))
In [698]: S.data
Out[698]: array([1, 1])
In [699]: S.row
Out[699]: array([0, 0], dtype=int32)
In [700]: S.col
Out[700]: array([0, 0], dtype=int32)

转换为密集(或CSR/CSC)确实合计,但不会改变S本身:

In [701]: S.A
Out[701]: array([[2]])
In [702]: S.data
Out[702]: array([1, 1])

您可以使用以下命令原地执行求和:

In [703]: S.sum_duplicates()
In [704]: S.data
Out[704]: array([2], dtype=int32)

我不知道有什么方法既可以删除重复项,也可以绕过该操作。我可以查一下相关的问题。

=

S.todok()进行原地求和(即,更改S)。查看该代码,我看到它称为self.sum_duplicates。以下代码复制了不带总和的数据:

In [727]: dok=sparse.dok_matrix((S.shape),dtype=S.dtype)
In [728]: dok.update(zip(zip(S.row,S.col),S.data))
In [729]: dok
Out[729]: 
<1x1 sparse matrix of type '<class 'numpy.int32'>'
    with 1 stored elements in Dictionary Of Keys format>
In [730]: print(dok)
  (0, 0)    1
In [731]: S
Out[731]: 
<1x1 sparse matrix of type '<class 'numpy.int32'>'
    with 2 stored elements in COOrdinate format>
In [732]: dok.A
Out[732]: array([[1]])

这是一个字典更新,因此最终的值是最后一个重复项。我在其他地方发现dok.update是将值添加到稀疏矩阵的一种相当快的方法。

tocsr固有地进行求和;tolil使用tocsr;因此这种todok方法可能是最简单的。

相关文章