假设我有一些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
有没有简单的方法来修改稀疏矩阵的子矩阵?
答案 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中有同样的问题。使用列表inds
,M[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