将矩阵列转换为对角矩阵并在没有 for 循环的情况下将它们包装起来
Transform matrix columns into diagonal matrices and wrap them up without for loops
我有 M
个向量,每个向量有 N
个条目(MxN
矩阵,如果你愿意的话):
A = [A1, A2, ... , AN]
B = [B1, B2, ... , BN]
...
Z = [Z1, Z2, ... , ZN]
我想转换这些以便输出为:
[[[A1, 0, ... , 0],
[0, B1, ... , 0],
...
[0, 0, ... , Z1]],
[[A2, 0, ... , 0],
[0, B2, ... , 0],
...
[0, 0, ... , Z2]],
...
[[AN, 0, ... , 0],
[0, BN, ... , 0],
...
[0, 0, ... , ZN]]]
目标是 不 完全使用 for 循环并仅通过 numpy
操作来实现。想法?
您可以使用 diag numpy 函数,例如
import numpy as np
A = [0, 1, 2]
B = [0, 1, 2]
C = [0, 1, 2]
# Merge lists into matrix
X = np.array([A, B, C])
# Index columns and merge into list of diagonal matrices
print([np.diag(X[:, 0]), np.diag(X[:, 1]), np.diag(X[:, 2])])
要使最后一步(以上)自动化,您可能需要使用 for 循环,例如
diag_list = []
for n in N:
diag_list.append(np.diag(X[:, n])
我发现了一个示例 here,它使用 np.apply_along_axis
填充多个对角线。
A = [11, 12, 13, 14]
B = [21, 22, 23, 24]
C = [31, 32, 33, 34]
D = [41, 42, 43, 44]
E = [51, 52, 53, 54]
Z = np.array([A, B, C, D, E])
构建 Z
后,您对其进行转置并用其值填充一个空的对角线数组:
>>> np.apply_along_axis(np.diag, -1, Z.T)
array([[[11, 0, 0, 0, 0],
[ 0, 21, 0, 0, 0],
[ 0, 0, 31, 0, 0],
[ 0, 0, 0, 41, 0],
[ 0, 0, 0, 0, 51]],
[[12, 0, 0, 0, 0],
[ 0, 22, 0, 0, 0],
[ 0, 0, 32, 0, 0],
[ 0, 0, 0, 42, 0],
[ 0, 0, 0, 0, 52]],
[[13, 0, 0, 0, 0],
[ 0, 23, 0, 0, 0],
[ 0, 0, 33, 0, 0],
[ 0, 0, 0, 43, 0],
[ 0, 0, 0, 0, 53]],
[[14, 0, 0, 0, 0],
[ 0, 24, 0, 0, 0],
[ 0, 0, 34, 0, 0],
[ 0, 0, 0, 44, 0],
[ 0, 0, 0, 0, 54]]])
虽然您的问题很清楚,但我们更愿意看到 [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]]])
如果最后这些步骤令人困惑,我建议您尝试创建自己的二维对角线阵列。从小处着手,并以此知识为基础。
我有 M
个向量,每个向量有 N
个条目(MxN
矩阵,如果你愿意的话):
A = [A1, A2, ... , AN]
B = [B1, B2, ... , BN]
...
Z = [Z1, Z2, ... , ZN]
我想转换这些以便输出为:
[[[A1, 0, ... , 0],
[0, B1, ... , 0],
...
[0, 0, ... , Z1]],
[[A2, 0, ... , 0],
[0, B2, ... , 0],
...
[0, 0, ... , Z2]],
...
[[AN, 0, ... , 0],
[0, BN, ... , 0],
...
[0, 0, ... , ZN]]]
目标是 不 完全使用 for 循环并仅通过 numpy
操作来实现。想法?
您可以使用 diag numpy 函数,例如
import numpy as np
A = [0, 1, 2]
B = [0, 1, 2]
C = [0, 1, 2]
# Merge lists into matrix
X = np.array([A, B, C])
# Index columns and merge into list of diagonal matrices
print([np.diag(X[:, 0]), np.diag(X[:, 1]), np.diag(X[:, 2])])
要使最后一步(以上)自动化,您可能需要使用 for 循环,例如
diag_list = []
for n in N:
diag_list.append(np.diag(X[:, n])
我发现了一个示例 here,它使用 np.apply_along_axis
填充多个对角线。
A = [11, 12, 13, 14]
B = [21, 22, 23, 24]
C = [31, 32, 33, 34]
D = [41, 42, 43, 44]
E = [51, 52, 53, 54]
Z = np.array([A, B, C, D, E])
构建 Z
后,您对其进行转置并用其值填充一个空的对角线数组:
>>> np.apply_along_axis(np.diag, -1, Z.T)
array([[[11, 0, 0, 0, 0],
[ 0, 21, 0, 0, 0],
[ 0, 0, 31, 0, 0],
[ 0, 0, 0, 41, 0],
[ 0, 0, 0, 0, 51]],
[[12, 0, 0, 0, 0],
[ 0, 22, 0, 0, 0],
[ 0, 0, 32, 0, 0],
[ 0, 0, 0, 42, 0],
[ 0, 0, 0, 0, 52]],
[[13, 0, 0, 0, 0],
[ 0, 23, 0, 0, 0],
[ 0, 0, 33, 0, 0],
[ 0, 0, 0, 43, 0],
[ 0, 0, 0, 0, 53]],
[[14, 0, 0, 0, 0],
[ 0, 24, 0, 0, 0],
[ 0, 0, 34, 0, 0],
[ 0, 0, 0, 44, 0],
[ 0, 0, 0, 0, 54]]])
虽然您的问题很清楚,但我们更愿意看到 [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]]])
如果最后这些步骤令人困惑,我建议您尝试创建自己的二维对角线阵列。从小处着手,并以此知识为基础。