如何在numpy中从现有数组创建对角线数组

3

我正在尝试从以下内容创建一个对角线NumPy数组:

[1,2,3,4,5,6,7,8,9]

期望结果:

[[ 0,  0,  1,  0,  0],
 [ 0,  0,  0,  2,  0],
 [ 0,  0,  0,  0,  3],
 [ 4,  0,  0,  0,  0],
 [ 0,  5,  0,  0,  0],
 [ 0,  0,  6,  0,  0],
 [ 0,  0,  0,  7,  0],
 [ 0,  0,  0,  0,  8],
 [ 9,  0,  0,  0,  0]]

什么是有效的做法?

2
你的输入和期望输出之间有什么关系?你到目前为止尝试过什么了吗? - Mazdak
除了列表之外,还有哪些输入参数? - Divakar
2个回答

2
您可以使用 整数数组索引 来设置输出的指定元素:
>>> import numpy as np
>>> a = [1,2,3,4,5,6,7,8,9]
>>> arr = np.zeros((9, 5), dtype=int)           # create empty array
>>> arr[np.arange(9), np.arange(2,11) % 5] = a  # insert a 
>>> arr
array([[0, 0, 1, 0, 0],
       [0, 0, 0, 2, 0],
       [0, 0, 0, 0, 3],
       [4, 0, 0, 0, 0],
       [0, 5, 0, 0, 0],
       [0, 0, 6, 0, 0],
       [0, 0, 0, 7, 0],
       [0, 0, 0, 0, 8],
       [9, 0, 0, 0, 0]])

np.fill_diagonal 有一个像这样的 wrap 模式,但它仅适用于主对角线。其他 diag 函数允许偏移,但不允许包装。 - hpaulj

1

受到np.fill_diagonal的启发,它可以进行包装但不能进行偏移:

In [308]: arr=np.zeros((9,5),int)
In [309]: arr.flat[2:45:6]=np.arange(1,10)
In [310]: arr
Out[310]: 
array([[0, 0, 1, 0, 0],
       [0, 0, 0, 2, 0],
       [0, 0, 0, 0, 3],
       [0, 0, 0, 0, 0],
       [4, 0, 0, 0, 0],
       [0, 5, 0, 0, 0],
       [0, 0, 6, 0, 0],
       [0, 0, 0, 7, 0],
       [0, 0, 0, 0, 8]])

(虽然由于某些原因,这里有第4个全零行)。
def fill_diagonal(a, val, wrap=False):
    ...       
    step = a.shape[1] + 1
    # Write the value out into the diagonal.
    a.flat[:end:step] = val

你丢失了数字 9,第四行似乎有错误。使用 step 在最后一列只有一个值且期望下一个值在下一行第一列的情况下会出现问题 :) - MSeifert
是的,我对此感到困惑。我会保留答案,以防有人发现这个“跨步”解决方案中的缺陷。 - hpaulj
问题在于你需要不同的“步骤”。对于第1->2行,需要6个步骤:从2到3、从4到5、从5到6、从6到7、从7到8以及从1到2;但对于第3->4和第8->9行,只需要1个步骤。 - MSeifert
这种包装方式是 fill_diagonal 的默认方式,直到版本1.6。 - hpaulj
因此,当正确排列时,步幅为6可以跳过长度为5的整行。 - hpaulj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接