fill_diagonal语法说明

时间:2019-09-05 19:04:36

标签: python numpy diagonal

我在理解np.fill_diagonal的实现方式时遇到了麻烦。

我找到了一条帖子here,该帖子解释了用某些值填充子对角线和超级对角线的方法,但我并不真正理解该函数的参数。这是代码:

a = np.zeros((4, 4))
b = np.ones(3)
np.fill_diagonal(a[1:], b)
np.fill_diagonal(a[:,1:], -b)

我不明白在这里如何使用fill_diagonal。我认为第二个参数必须是scalar。另外,我不理解“ a”的片段发生了什么。

2 个答案:

答案 0 :(得分:1)

“对于具有a.ndim >= 2的数组a,对角线是索引为a[i, ..., i]完全相同的位置的列表。此函数就地修改输入数组,不返回值。 (Source)此方法的文档说b应该是标量,但是如果b是长度等于输入数组对角线长度的数组,则它将填写b的值作为对角线。

关键是b中的元素数等于a的每个子阵列对角线上的元素数。子数组的第 n 个对角线值用b的第 n 个值填充。

a的第一个子数组是a的第一行以外的所有子数组(这意味着3行4列),因此对角元素的数量为3。

a的第二个子数组是a的最后三列(4 x 3矩阵),它也只有3个对角线元素。

================================================ =========================
感谢G. Anderson的评论。我正在将其编辑到帖子中以引起注意:

“值得注意的是,b不必与填充的对角线长度相同。如果b较长,则对角线的n个元素将被b的前n个元素填充。如果n较短,比对角线,那么将重复b来填充对角线“

答案 1 :(得分:0)

您的示例涉及填充原始数组的切片views

In [79]: a = np.zeros((4, 4)) 
    ...: b = np.arange(1,5)                                                                                  
In [80]:        

简单的情况-填充整个数组:

In [80]: np.fill_diagonal(a,b)                                                                               
In [81]: a                                                                                                   
Out[81]: 
array([[1., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 3., 0.],
       [0., 0., 0., 4.]])

fill_diagonal接受要填充的数组,并将值放在对角线中。文档确实说scalar,但这太过严格了。如我所示,它可以是大小合适的一维数组。

In [82]: a = np.zeros((4, 4)) 
    ...: b = np.arange(1,4)                                                                                  

填充最后3行:

In [83]: a[1:]                                                                                               
Out[83]: 
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
In [84]: np.fill_diagonal(a[1:],b)                                                                           
In [85]: a                                                                                                   
Out[85]: 
array([[0., 0., 0., 0.],
       [1., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 3., 0.]])

In [86]: a = np.zeros((4, 4)) 
    ...: b = np.arange(1,4)

填写最后3列:

In [87]: a[:,1:]                                                                                             
Out[87]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
In [88]: np.fill_diagonal(a[:,1:],b)                                                                         
In [89]: a                                                                                                   
Out[89]: 
array([[0., 1., 0., 0.],
       [0., 0., 2., 0.],
       [0., 0., 0., 3.],
       [0., 0., 0., 0.]])

关键是fill_diagonal就地工作,而a[1:]a[:,1:]产生a的视图。

填充后查看a的切片:

In [90]: a[:,1:]                                                                                             
Out[90]: 
array([[1., 0., 0.],
       [0., 2., 0.],
       [0., 0., 3.],
       [0., 0., 0.]])

文档演示了np.fliplr(a)的用法。同样,创建一个view,可以在适当位置进行修改。

实际写入是通过以下方式完成的:

a.flat[:end:step] = val

其中endstep是根据尺寸计算得出的。例如,要填充3x3数组,我们可以写入每个第4个元素。

In [96]: a[:,1:].ravel()                                                                                     
Out[96]: array([1., 0., 0., 0., 2., 0., 0., 0., 3., 0., 0., 0.])