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

Mic*_*ael 6 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
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 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
Run Code Online (Sandbox Code Playgroud)

每种格式的文档都表明它擅长什么,哪些不好.但它没有一个清晰的列表,其中列出了哪些操作已定义.

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
  ...
Run Code Online (Sandbox Code Playgroud)

dok_matrix 还实现了索引.

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

sparse.coo_matrix(([6],([5],[7])), shape=(10,10))
Run Code Online (Sandbox Code Playgroud)

如果您有更多的任务,构建更大data,i,j列表(或一维数组),当完成构建稀疏矩阵.


Gab*_*iel 2

bsr 的文档是这里bsr 矩阵,csr 的文档是这里csr 矩阵。在转向 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)) )
Run Code Online (Sandbox Code Playgroud)

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

A.todense()
Run Code Online (Sandbox Code Playgroud)

但是,您无法使用此模式即时操作矩阵。您可以做的是修改矩阵的本机 scipy 表示形式。这涉及 3 个属性,indicesindptr、 和data。首先,我们可以检查我们已经创建的数组的这些属性的值。

>>> 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)
Run Code Online (Sandbox Code Playgroud)

data和之前一样,是我们想要在矩阵中包含值的一维数组。不同之处在于该数据的位置现在由indices和指定,indptr而不是rowcolindices相当简单。它只是每个数据条目所在列的列表。它将始终具有相同的大小和数组dataindptr有点棘手。它让数据结构知道每个数据条目位于哪一行。引用文档,

行的列索引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] )   
Run Code Online (Sandbox Code Playgroud)

接下来我们更新indices以指示第 10 列将位于,

A.indices = np.array( [4,7], dtype=np.int32 )
Run Code Online (Sandbox Code Playgroud)

最后我们通过修改来指示它将位于哪一行indptr

A.indptr = np.array( [0,0,0,1,1,1,2], dtype=np.int32 )
Run Code Online (Sandbox Code Playgroud)

indices和的数据类型设置为 很重要indptr np.int32。可视化所发生内容的一种方法是,当您从具有数据的行移至另一行时,数字indptr会发生变化。另请注意,此类数组可用于构造稀疏矩阵ii+1

B = csr_matrix( (data,indices,indptr) )
Run Code Online (Sandbox Code Playgroud)

如果它像您尝试的那样简单地索引到数组中,那就太好了,但实现尚未实现。这至少应该足以让您开始。