Python 在numpy中更改矩阵对角线的值

Python 在numpy中更改矩阵对角线的值,python,numpy,Python,Numpy,如何在numpy中更改矩阵对角线的值 我检查了,但是那里的函数没有在numpy v 1.3.0中实现 假设我们有一个np.array X,我想把对角线的所有值都设置为0 def replaceDiagonal(matrix, replacementList): for i in range(len(replacementList)): matrix[i][i] = replacementList[i] 其中大小是n x n矩阵中的n。您是否尝试过numpy.fill\u

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

我检查了,但是那里的函数没有在numpy v 1.3.0中实现

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

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

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

您是否尝试过
numpy.fill\u diagonal
?请参见下面的内容和此。或文档中的以下内容(尽管当前已损坏):


如果您使用的numpy版本没有
fill\u diagonal
(用于将对角线设置为常数)或
diag\u index\u 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很好…):


(只有在Python3中才需要调用
list
,其中
zip
返回一个迭代器。)

下面是另一种很好的方法。如果需要阵列主对角线的一维视图,请使用:

A.ravel()[:A.shape[1]**2:A.shape[1]+1]
A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1]
A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1]
对于第i次超对角线使用:

A.ravel()[:A.shape[1]**2:A.shape[1]+1]
A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1]
A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1]
对于第i次对角线使用:

A.ravel()[:A.shape[1]**2:A.shape[1]+1]
A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1]
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和更高版本中,数组的“对角线”方法将返回视图而不是副本。 虽然还没有做出改变,但希望在某个时候,这种获取视图的技巧不再是必要的。 请参见

最小值。代码

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

您可以执行以下操作

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

indices_diagonal = np.diag_indices(4)

yourarray[indices_diagonal] = Val

您使用的是什么版本的numpy
np.diag\u index\u from
是在v1.4中添加的是的,你是对的,我目前正在使用python v1.3。0@LangerHansIslands希望您指的是numpy 1.3,而不是Python1.3(它出现在90年代中期…:p)+1这是在numpy中实现这一点的正确方法。内置总是比使用两个for循环一次迭代一个数组元素更可取。或者
n=len(替换列表);矩阵[:n,:n]=替换列表
。这在C中而不是在Python中进行循环,因此速度会快得多。@Dougal:太棒了,我不知道。你能把它作为答案发布吗?为了让未来的读者明白,
mat[:n,:n]=0
将整个数组/矩阵设置为0,而不仅仅是对角线元素
zip
version确实做了诊断。@gorlum0哇-谢谢你指出这一点。我只是编辑来修复它(那里实际上不需要
zip
)`。很酷,甚至是裸露的
范围
。这种含蓄的东西很难让人知道。又好又粗糙,我喜欢!唯一需要注意的是,我认为您将获得中描述的
wrap=True
行为。你也许可以解决这个问题,给你的切片增加一个足够的停止值。谢谢你,接得好。我只是编辑了它来修复这个问题和其他一些问题。