创建稀疏 DIA 矩阵,然后更改列

Create sparse DIA matrix, and then change columns

我有两个向量 tdelta - 两个向量的长度都是 n。我想用该向量创建一个稀疏 DIA 矩阵 A,然后调整列:对于所有 i,我想移动 ith 中的条目 [=16] =] 左边 delta[i] 列。

一种控制列的简单方法是采用 COO 格式。这是我认为可行的方法:

from scipy.sparse import diags
A = diags([t], offsets=[-1]).tocoo()
A.col = A.col - delta

然而,在我的例子中A.nnz == len(A.col)只是216,而tdelta的长度是239。鉴于 nnz 存储 "Number of stored values, including explicit zeros.",我不明白这是怎么发生的。

我该如何解决这个问题?这是我的示例数据:

from numpy import np
t = np.array([ 2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.655,
        2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.655,
        2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.655,  2.155,
        2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  2.155,
        2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  2.155,
        2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  2.155,  1.655,
        1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.655,
        1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.655,
        1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.655,  1.155,
        1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  1.155,
        1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  1.155,
        1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  1.155,  0.655,
        0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.655,
        0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.655,
        0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.655,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,
        0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.405,  0.   ,
        0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,
        0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,
        0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ])
delta = np.array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
   5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
   5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
   5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
   5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
   4, 5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
   4, 4, 5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4,
   4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
   4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3,
   3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 0, 2, 2, 3, 2,
   1, 3, 4, 3, 0, 3, 5, 4, 1, 0])
In [29]: t = np.array([1.2, 3.2, 4, 0, 0])
In [30]: A = sparse.diags([t], offsets=[-1])
In [31]: A
Out[31]: 
<6x6 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements (1 diagonals) in DIAgonal format>

转换为 coo 会去掉 0。

In [32]: Ac = A.tocoo()
In [33]: Ac
Out[33]: 
<6x6 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in COOrdinate format>

查看 A.tocoo 的代码(diacoo 版本)。它有 (self.data != 0) 个掩码。


如果我直接创建 coo 矩阵,它至少会暂时保留零:

In [58]: A.A
Out[58]: 
array([[ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 1.2,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  3.2,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  4. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ]])
In [59]: M = sparse.coo_matrix((t, (np.arange(1,6),np.arange(5))),shape=(6,6))
In [60]: M
Out[60]: 
<6x6 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements in COOrdinate format>
In [61]: M.A
Out[61]: 
array([[ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 1.2,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  3.2,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  4. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ]])

就地零删除:

In [64]: M.eliminate_zeros()
In [65]: M
Out[65]: 
<6x6 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in COOrdinate format>