访问/修改稀疏scipy矩阵的子矩阵

时间:2015-11-03 04:08:46

标签: python python-2.7 scipy

假设我有一些Scipy稀疏csr矩阵A和一组索引inds=[i_1,...,i_n]。我可以通过inds访问A[inds,:][:,inds]中给出的行和列给出的子矩阵。但我无法弄清楚如何修改它们。所有以下都失败(即不改变矩阵值):

  • A[inds,:][:,inds] *= 5.0
  • (A[inds,:][:,inds]).multiply(5.0)
  • A[inds,:][:,inds] = 5.0

有没有简单的方法来修改稀疏矩阵的子矩阵?

1 个答案:

答案 0 :(得分:2)

sparse中访问块或子矩阵的规则与numpy的[编辑:类似]相同。 2个索引数组需要是可广播的。最简单的方法是使第一个成为列向量。

我将说明:

In [13]: A = np.arange(24).reshape(4,6)

In [14]: M=sparse.csr_matrix(A)

In [15]: A[[[1],[2]],[1,2,3]]
Out[15]: 
array([[ 7,  8,  9],
       [13, 14, 15]])

In [16]: M[[[1],[2]],[1,2,3]].A
Out[16]: 
array([[ 7,  8,  9],
       [13, 14, 15]], dtype=int32)

In [17]: idx1=np.array([1,2])[:,None]

In [18]: idx1
Out[18]: 
array([[1],
       [2]])

In [19]: idx2=np.array([1,2,3])

In [20]: M[idx1, idx2].A
Out[20]: 
array([[ 7,  8,  9],
       [13, 14, 15]], dtype=int32)

In [21]: M[idx1, idx2] *= 2

In [22]: M.A
Out[22]: 
array([[ 0,  1,  2,  3,  4,  5],
       [ 6, 14, 16, 18, 10, 11],
       [12, 26, 28, 30, 16, 17],
       [18, 19, 20, 21, 22, 23]], dtype=int32)

M[inds,:][:,inds]在稀疏和numpy中有同样的问题。使用列表indsM[inds,:]是原始列表的副本,而不是view。我已经参考numpy中的数据缓冲区了。我不太确定如何用稀疏来证明它。

粗略地说,A[...][...] = ...会转换为A.__getitem__(...).__setitem__(...,...)。如果A.__getitem__(...)是副本,则修改它不会自行修改A

实际上,稀疏矩阵在视图和副本之间没有区别。大多数(如果不是全部)索引都会产生副本。 M[:2,:]是一个副本,即使A[:2,:]是一个视图。

我还应该补充一点,改变稀疏矩阵的值是你应该谨慎做的事情。就地乘法(*=)没问题。

不支持添加:

In [31]: M[idx1, idx2] += 2
...
NotImplementedError: 

修改值可能会产生效率警告 - 如果它将0值变为非零值:

In [33]: M[:2, :2] = 3
/usr/lib/python3/dist-packages/scipy/sparse/compressed.py:690: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)

此前问题的np.ix_答案也适用于此 Python - list of same columns / rows from matrix

M[np.ix_([1,2],[1,2,3])].A