虽然您的问题很清楚,但我们更愿意看到 [MCVE](该标签在评论中展开,请参阅 SO 介绍)。当要求无循环解决方案时,展示一个有效的循环解决方案是礼貌的——这给了我们一些测试依据。我至少想证明我的答案有效。
所以这里是我最小的工作示例 - 使用循环解决方案:
In [308]: M = np.stack([np.arange(i,j) for i,j in zip([1,11,21],[5,15,25])])
In [309]: M.shape
Out[309]: (3, 4)
In [310]: M
Out[310]:
array([[ 1, 2, 3, 4],
[11, 12, 13, 14],
[21, 22, 23, 24]])
In [311]: np.stack([np.diag(M[:,i]) for i in range(4)])
Out[311]:
array([[[ 1, 0, 0],
[ 0, 11, 0],
[ 0, 0, 21]],
[[ 2, 0, 0],
[ 0, 12, 0],
[ 0, 0, 22]],
[[ 3, 0, 0],
[ 0, 13, 0],
[ 0, 0, 23]],
[[ 4, 0, 0],
[ 0, 14, 0],
[ 0, 0, 24]]])
np.diagonal让我们指定轴。因此,例如,我们可以使用它从以下位置提取起始数组Out[311]:
In [318]: np.diagonal(Out[311],axis1=1, axis2=2)
Out[318]:
array([[ 1, 11, 21],
[ 2, 12, 22],
[ 3, 13, 23],
[ 4, 14, 24]])
我没有(直接)看到多维建筑。我们可以在文档中挖掘更多,或者查看现有代码来构造一个等价物。或者只是接受该循环的时间损失:)
这些diag(onal)函数使用flat索引来提高速度,但使用多维索引更容易。我们可以访问这些相同的值
In [319]: Out[311][:,np.arange(3),np.arange(3)]
Out[319]:
array([[ 1, 11, 21],
[ 2, 12, 22],
[ 3, 13, 23],
[ 4, 14, 24]])
我们可以使用相同的索引来分配值。
In [320]: res = np.zeros((4,3,3),int)
In [321]: res[:,np.arange(3), np.arange(3)] = M.T
In [322]: res
Out[322]:
array([[[ 1, 0, 0],
[ 0, 11, 0],
[ 0, 0, 21]],
[[ 2, 0, 0],
[ 0, 12, 0],
[ 0, 0, 22]],
[[ 3, 0, 0],
[ 0, 13, 0],
[ 0, 0, 23]],
[[ 4, 0, 0],
[ 0, 14, 0],
[ 0, 0, 24]]])
如果这些最后的步骤令人困惑,我建议您尝试创建自己的二维对角线阵列。从小处着手,并以这些知识为基础。