如何在numpy中更改矩阵对角线的值?
我检查了Numpy修改ndarray对角线,但是在numpy v 1.3.0中没有实现的功能.
假设我们有一个np.array X,我想将对角线的所有值都设置为0.
Mel*_*kor 42
你试过numpy.fill_diagonal吗?请参阅以下答案和此讨论.或者文档中的以下内容(虽然目前已损坏):
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html
Dou*_*gal 13
如果你使用的是没有的numpy版本fill_diagonal(将对角线设置为常量的正确方法),或者diag_indices_from你可以通过数组切片很容易地做到这一点:
# assuming a 2d square array
n = mat.shape[0]
mat[range(n), range(n)] = 0
Run Code Online (Sandbox Code Playgroud)
这比Python中的显式循环要快得多,因为循环发生在C中并且可能是矢量化的.
关于这一点的一个好处是你也可以用一个元素列表填充对角线,而不是一个常量值(比如diagflat,但是用于修改现有矩阵而不是创建一个新矩阵).例如,这会将矩阵的对角线设置为0,1,2,...:
# again assuming 2d square array
n = mat.shape[0]
mat[range(n), range(n)] = range(n)
Run Code Online (Sandbox Code Playgroud)
如果你需要支持更多的数组形状,这就更复杂了(这就是为什么fill_diagonal很好......):
m[list(zip(*map(range, m.shape)))] = 0
Run Code Online (Sandbox Code Playgroud)
(list只有在Python 3中才需要调用,zip返回迭代器.)
Ian*_*anH 11
这是另一种做到这一点的好方法.如果你想要一个数组的主对角线的一维视图使用:
A.ravel()[:A.shape[1]**2:A.shape[1]+1]
Run Code Online (Sandbox Code Playgroud)
对于我的超对角线使用:
A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1]
Run Code Online (Sandbox Code Playgroud)
对于第i个对角线使用:
A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1]
Run Code Online (Sandbox Code Playgroud)
或者一般来说,对于主对角线为0的第i个对角线,子对角线为负,超对角线为正,使用:
A.ravel()[max(i,-A.shape[1]*i):max(0,(A.shape[1]-i))*A.shape[1]:A.shape[1]+1]
Run Code Online (Sandbox Code Playgroud)
这些是视图而不是副本,因此它们将更快地运行以提取对角线,但对新数组对象所做的任何更改都将应用于原始数组.在我的机器上,当将主对角线设置为常数时,它们比fill_diagonal函数运行得更快,但情况可能并非总是如此.它们还可用于将一组值分配给对角线而不仅仅是一个常量.
注意:对于小数组,使用flatNumPy数组的属性可能会更快.如果速度是一个主要问题,那么制作A.shape[1]一个局部变量是值得的.此外,如果数组不连续,ravel()将返回一个副本,因此,为了将值分配给跨步切片,有必要创造性地切片用于生成跨步切片的原始数组(如果它是连续的)或者使用该flat属性.
此外,最初计划在NumPy 1.10中以后,数组的"对角线"方法将返回视图而不是副本.尽管如此,这种变化还没有实现,但希望在某种程度上这种获取观点的技巧将不再是必要的.见http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.diagonal.html