如何使用scipy编辑稀疏矩阵中的单元格?

时间:2014-07-09 23:27:49

标签: python matrix scipy sparse-matrix

我正在尝试操作稀疏矩阵中的一些数据。一旦我创建了一个,我如何在其中添加/更改/更新值?这看起来非常基本,但我在稀疏矩阵类的文档中或在Web上找不到它。我想我错过了至关重要的事情。

这是我尝试这样做的失败方式,与普通数组相同。

>>> from scipy.sparse import bsr_matrix
>>> A = bsr_matrix((10,10))
>>> A[5][7] = 6

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    A[5][7] = 6
  File "C:\Python27\lib\site-packages\scipy\sparse\bsr.py", line 296, in __getitem__
    raise NotImplementedError
NotImplementedError

2 个答案:

答案 0 :(得分:5)

有几种稀疏矩阵格式。有些更适合索引。实现它的是lil_matrix

Al = A.tolil()
Al[5,7] = 6  # the normal 2d matrix indexing notation
print Al
print Al.A # aka Al.todense()
A1 = Al.tobsr()  # if it must be in bsr format

每种格式的文档都表明它擅长什么,哪些不好。但它没有一个整齐的清单,列出哪些操作定义了哪些。

Advantages of the LIL format
  supports flexible slicing
  changes to the matrix sparsity structure are efficient
  ...
Intended Usage
  LIL is a convenient format for constructing sparse matrices
  ...

dok_matrix也实现了索引。

coo_matrix的基础数据结构很容易理解。它本质上是coo_matrix((data, (i, j)), [shape=(M, N)])定义的参数。要创建相同的矩阵,您可以使用:

sparse.coo_matrix(([6],([5],[7])), shape=(10,10))

如果您有更多分配,请构建更大的dataij列表(或1d数组),并在完成构建稀疏矩阵时使用。

答案 1 :(得分:2)

bsr的文档在bsr matrix,csr的文档在csr matrix。在转移到bsr之前理解csr可能是值得的。唯一的区别是bsr的条目本身就是矩阵,而csr中的基本单位是标量。

我不知道在创建矩阵后是否有超级简单的方法来操纵矩阵,但这里有一些你正在尝试做的事情的例子,

import numpy as np
from scipy.sparse import bsr_matrix, csr_matrix

row = np.array( [5] )
col = np.array( [7] )
data = np.array( [6] )
A = csr_matrix( (data,(row,col)) )

这是一种简单的语法,您可以在其中列出数组data中矩阵中所需的所有数据,然后使用rowcol指定数据的去向。请注意,这将使矩阵尺寸足够大,以便将元素保存在最大的行和列中(在本例中为6x8矩阵)。您可以使用todense()方法以标准形式查看矩阵。

A.todense()

但是,您无法使用此模式动态操作矩阵。你可以做的是修改矩阵的原始scipy表示。这涉及3个属性indicesindptrdata。首先,我们可以检查我们已经创建的数组的这些属性的值。

>>> print A.data
array([6])

>>> print A.indices
array([7], dtype=int32)

>>> print A.indptr
array([0, 0, 0, 0, 0, 0, 1], dtype=int32)

data和以前一样,是矩阵中我们想要的一维数组。不同之处在于,此数据的位置现在由indicesindptr而不是rowcol指定。 indices非常简单。它只是每个数据条目所在列的列表。它将始终具有相同的大小和data数组。 indptr有点棘手。它允许数据结构知道每个数据条目所在的行。引用文档,

  

i的列索引存储在indices[indptr[i]:indptr[i+1]]

从这个定义中我们可以看到indptr的大小总是矩阵中的行数+ 1.需要一点时间来习惯它,但是要处理每一行的值会给你一些直觉。请注意,所有条目都是零,直到最后一个。这意味着行i=0-4的列索引将存储在indices[0:0]中,即空数组。这是因为这些行都是零。最后,在最后一行i=5,我们得到indices[0:1]=7,告诉我们数据条目data[0:1]位于第5行第7列。

现在假设我们想在第2行第4列添加值10.我们首先将它放入data属性,

A.data = np.array( [10,6] )   

接下来我们更新indices以指示第10列将在

A.indices = np.array( [4,7], dtype=np.int32 )

最后我们通过修改indptr

来指明它将在哪一行
A.indptr = np.array( [0,0,0,1,1,1,2], dtype=np.int32 )

您必须使数据类型为indicesindptr np.int32。可视化indptr中的内容的一种方法是,当您从具有数据的行的i移动到i+1时,数字会发生变化。另请注意,这些数组可用于构造稀疏矩阵

B = csr_matrix( (data,indices,indptr) )

如果它像你尝试的那样简单地索引到数组中会很容易,但是实现还没有。这应该足以让你至少开始。