更改 numpy 中矩阵对角线的值

问题描述 投票:0回答:7

如何更改 numpy 中矩阵对角线的值?

我检查了Numpy修改ndarray对角线,但是那里的功能在numpy v 1.3.0中没有实现。

假设我们有一个 np.array X,我想将对角线的所有值设置为 0。

python numpy
7个回答
56
投票

你尝试过吗

numpy.fill_diagonal
?请参阅以下答案和此讨论。或者文档中的以下内容:

https://numpy.org/doc/stable/reference/ generated/numpy.fill_diagonal.html


17
投票

如果您使用的 numpy 版本没有

fill_diagonal
(将对角线设置为常量的正确方法)或
diag_indices_from
,您可以通过数组切片轻松完成此操作:

# assuming a 2d square array
n = mat.shape[0]
mat[range(n), range(n)] = 0

这比 Python 中的显式循环快得多,因为循环发生在 C 中并且可能被矢量化。

这样做的一个好处是,您还可以用元素列表而不是常数值填充对角线(如

diagflat
,但用于修改现有矩阵而不是创建新矩阵)。例如,这会将矩阵的对角线设置为 0, 1, 2, ...:

# again assuming 2d square array
n = mat.shape[0]
mat[range(n), range(n)] = range(n)

如果你需要支持更多的数组形状,这会更复杂(这就是为什么 fill_diagonal 很好......):

m[list(zip(*map(range, m.shape)))] = 0

(仅在 Python 3 中才需要

list
调用,其中
zip
返回迭代器。)


15
投票

您可以使用

numpy.diag_indices_from()
获取数组对角线元素的索引。然后设置这些索引的值。

X[np.diag_indices_from(X)] = 0.

示例:

>>> import numpy as np
>>> X = np.random.rand(5, 5)

>>> print(X)
[[0.59480384 0.20133725 0.59147423 0.22640441 0.40898203]
 [0.65230581 0.57055258 0.97009881 0.58535275 0.32036626]
 [0.71524332 0.73424734 0.92461381 0.38704119 0.08147428]
 [0.18931865 0.97366736 0.11482649 0.82793141 0.13347333]
 [0.47402986 0.73329347 0.18892479 0.11883424 0.78718883]]

>>> X[np.diag_indices_from(X)] = 0
>>> print(X)
[[0.         0.20133725 0.59147423 0.22640441 0.40898203]
 [0.65230581 0.         0.97009881 0.58535275 0.32036626]
 [0.71524332 0.73424734 0.         0.38704119 0.08147428]
 [0.18931865 0.97366736 0.11482649 0.         0.13347333]
 [0.47402986 0.73329347 0.18892479 0.11883424 0.        ]]

11
投票

这是另一个好方法。如果您想要数组主对角线的一维视图,请使用:

A.ravel()[:A.shape[1]**2:A.shape[1]+1]

对于第 i 个超对角线的使用:

A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1]

对于第 i 个下对角线的使用:

A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1]

或者一般来说,对于主对角线为 0 的第 i 个对角线,次对角线为负,上对角线为正,使用:

A.ravel()[max(i,-A.shape[1]*i):max(0,(A.shape[1]-i))*A.shape[1]:A.shape[1]+1]

这些是视图而不是副本,因此它们提取对角线的速度会更快,但对新数组对象所做的任何更改都将应用于原始数组。 在我的机器上,当将主对角线设置为常量时,它们的运行速度比 fill_diagonal 函数更快,但情况可能并不总是如此。它们还可以用于将值数组分配给对角线,而不仅仅是一个常量。

注意:对于小型数组,使用 NumPy 数组的

flat
属性可能会更快。 如果速度是一个主要问题,那么将
A.shape[1]
设为局部变量可能是值得的。 另外,如果数组不连续,
ravel()
将返回一个副本,因此,为了将值分配给跨步切片,有必要创造性地对用于生成跨步切片的原始数组进行切片(如果它是连续的) )或使用
flat
属性。

此外,最初计划在 NumPy 1.10 及更高版本中,数组的“对角线”方法将返回视图而不是副本。 虽然这种改变还没有发生,但希望在某个时候不再需要这种获取视图的技巧。 请参阅http://docs.scipy.org/doc/numpy-dev/reference/ generated/numpy.diagonal.html


1
投票
def replaceDiagonal(matrix, replacementList):
    for i in range(len(replacementList)):
        matrix[i][i] = replacementList[i]

其中大小为 n x n 矩阵中的 n。


1
投票
>>> a = numpy.random.rand(2,2)
>>> a
array([[ 0.41668355,  0.07982691], 
       [ 0.60790982,  0.0314224 ]])
>>> a - numpy.diag(numpy.diag(a))
array([[ 0.        ,  0.07982691],
       [ 0.60790982,  0.        ]])

1
投票

您可以执行以下操作。

假设你的矩阵是 4 * 4 矩阵。

indices_diagonal = np.diag_indices(4)

yourarray[indices_diagonal] = Val
© www.soinside.com 2019 - 2024. All rights reserved.