【问题标题】:Numpy: Affect diagonal elements of matrix prior to 1.10Numpy:在 1.10 之前影响矩阵的对角元素
【发布时间】:2015-01-10 11:52:13
【问题描述】:

我想改变二维矩阵的对角线元素。这些是主对角线和非主对角线。

numpy.diagonal() 在 NumPy 1.10 中,它将返回一个读/写视图,写入返回的 数组会改变你原来的数组。

numpy.fill_diagonal()numpy.diag_indices() 仅适用于主对角线元素

这是我的用例:我想重新创建以下形式的矩阵,考虑到我拥有所有 xy,使用对角线表示法非常简单, z 作为数组。

【问题讨论】:

标签: python numpy matrix diagonal


【解决方案1】:

您始终可以使用切片将值或数组分配给对角线。

传入行索引列表和列索引列表可让您直接(有效地)访问位置。例如:

>>> z = np.zeros((5,5))
>>> z[np.arange(5), np.arange(5)] = 1 # diagonal is 1
>>> z[np.arange(4), np.arange(4) + 1] = 2 # first upper diagonal is 2
>>> z[np.arange(4) + 1, np.arange(4)] = [11, 12, 13, 14] # first lower diagonal values

将零数组z 更改为:

array([[  1.,   2.,   0.,   0.,   0.],
       [ 11.,   1.,   2.,   0.,   0.],
       [  0.,  12.,   1.,   2.,   0.],
       [  0.,   0.,  13.,   1.,   2.],
       [  0.,   0.,   0.,  14.,   1.]])

通常对于名为zk x k 数组,您可以使用

设置ith 上对角线
z[np.arange(k-i), np.arange(k-i) + i]

ith 下对角线与

z[np.arange(k-i) + i, np.arange(k-i)]

注意:如果你想避免多次调用np.arange,你可以简单地写一次ix = np.arange(k),然后根据需要对该范围进行切片:

np.arange(k-i) == ix[:-i]

【讨论】:

    【解决方案2】:

    试试这个:

    >>> A = np.zeros((6,6))
    >>> i,j = np.indices(A.shape)
    >>> z = [1, 2, 3, 4, 5]
    

    现在您可以直观地访问任何对角线:

    >>> A[i==j-1] = z
    >>> A
    array([[ 0.,  1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  2.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  3.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  4.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  5.],
           [ 0.,  0.,  0.,  0.,  0.,  0.]])
    

    同样的方式你可以将数组分配给A[i==j]

    【讨论】:

    • 尚未将性能与@ajcrs 答案进行比较,但为了简单起见,我喜欢这个。
    • @FooBar 这个方法在语法上肯定比我的简单:-) 但是在性能方面,为更大的矩阵构造掩码(使用i==j-1)效率不高。在 1000x1000 矩阵上,设置第一个上对角线比直接指定索引慢大约 100 倍。这是因为您需要进行一百万次== 比较来构建布尔掩码(更不用说在内存中拥有大型布尔矩阵)。当然,这是否重要取决于您的用例。
    【解决方案3】:

    这是另一种只是为了好玩的方法。您可以编写自己的对角线函数来返回您需要的对角线视图。

    import numpy as np
    
    def diag(a, k=0):
        if k > 0:
            a = a[:, k:]
        elif k < 0:
            a = a[-k:, :]
    
        shape = (min(a.shape),)
        strides = (sum(a.strides),)
        return np.lib.stride_tricks.as_strided(a, shape, strides)
    
    a = np.arange(20).reshape((4, 5))
    diag(a, 2)[:] = 88
    diag(a, -2)[:] = 99
    print(a)
    # [[ 0  1 88  3  4]
    #  [ 5  6  7 88  9]
    #  [99 11 12 13 88]
    #  [15 99 17 18 19]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      • 2021-02-28
      • 1970-01-01
      相关资源
      最近更新 更多