如何更改 numpy 中矩阵对角线的值?
我检查了Numpy修改ndarray对角线,但是那里的功能在numpy v 1.3.0中没有实现。
假设我们有一个 np.array X,我想将对角线的所有值设置为 0。
你尝试过吗
numpy.fill_diagonal
?请参阅以下答案和此讨论。或者文档中的以下内容:
https://numpy.org/doc/stable/reference/ generated/numpy.fill_diagonal.html
如果您使用的 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
返回迭代器。)
您可以使用
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. ]]
这是另一个好方法。如果您想要数组主对角线的一维视图,请使用:
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
def replaceDiagonal(matrix, replacementList):
for i in range(len(replacementList)):
matrix[i][i] = replacementList[i]
其中大小为 n x n 矩阵中的 n。
>>> 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. ]])
您可以执行以下操作。
假设你的矩阵是 4 * 4 矩阵。
indices_diagonal = np.diag_indices(4)
yourarray[indices_diagonal] = Val