Skip to main content
 首页 » 编程设计

python之组合数组以产生新的集合数组

2024年08月13日40shanyou

我有三个 (n,n) 数组,我需要以非常特定的方式组合它们,以便产生 n*n 个新数组,这些数组必须合并成一个大阵。

我基本上需要从每个数组中取出一个元素并创建一个新的 (3,3) 数组,其中对角线是三个元素(其余为空),然后组合这些新数组合二为一。

解释起来有点困难。我试图在下面举一个例子,希望它能说明我正在尝试做什么。

示例:给定三个 (2,3) 数组:

a = np.array([[2,5,9], [7,2,4]]) 
b = np.array([[3,6,2], [1,6,8]]) 
c = np.array([[8,7,4], [9,3,1]]) 

以a、b和c中的元素作为对角线创建六个数组:

T1 = ([[ 2, 0, 0], 
       [ 0, 3, 0], 
       [ 0, 0, 8]]) 
 
T2 = ([[ 5, 0, 0], 
       [ 0, 6, 0], 
       [ 0, 0, 7]]) 
 
T3 = ([[ 9, 0, 0], 
       [ 0, 2, 0], 
       [ 0, 0, 4]]) 
 
T4 = ([[ 7, 0, 0], 
       [ 0, 1, 0], 
       [ 0, 0, 9]]) 
 
T5 = ([[ 2, 0, 0], 
       [ 0, 6, 0], 
       [ 0, 0, 3]) 
 
T6 = ([[ 4, 0, 0], 
       [ 0, 8, 0], 
       [ 0, 0, 1]]) 

将六个数组组合起来产生

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

如在

array([[ T1, T2, T3], 
       [ T4, T5, T6]]) 

*这六个数组本身不需要作为单独的数组,只需要最后一个数组。我刚刚选择了这条路线,因为它使最终路线的组成更加明显。

请您参考如下方法:

可以用einsum来完成:

ABC = np.array((a,b,c)) 
i,j,k = ABC.shape 
out = np.zeros((i*j,i*k),ABC.dtype) 
np.einsum("jiki->ijk",out.reshape(j,i,k,i))[...] = ABC 
out 
# array([[2, 0, 0, 5, 0, 0, 9, 0, 0], 
#        [0, 3, 0, 0, 6, 0, 0, 2, 0], 
#        [0, 0, 8, 0, 0, 7, 0, 0, 4], 
#        [7, 0, 0, 2, 0, 0, 4, 0, 0], 
#        [0, 1, 0, 0, 6, 0, 0, 8, 0], 
#        [0, 0, 9, 0, 0, 3, 0, 0, 1]]) 

解释:

reshape 有什么作用?

                            axis 2 (size k) 
                       /-----------------------\ 
                            axis 3 (size i) 
                       /-----\  /-----\  /-----\    
a  s /     a  s /    [[2, 0, 0, 5, 0, 0, 9, 0, 0], 
x  i |     x  i |     [0, 3, 0, 0, 6, 0, 0, 2, 0], 
i  z |     i  z \     [0, 0, 8, 0, 0, 7, 0, 0, 4], 
s  e |     s  e /     [7, 0, 0, 2, 0, 0, 4, 0, 0], 
     |          |     [0, 1, 0, 0, 6, 0, 0, 8, 0], 
0  j \     1  i \     [0, 0, 9, 0, 0, 3, 0, 0, 1]] 

它将 3x3 对角矩阵隔离到轴 1,3。

einsum 在这里做什么?

它将 reshape 后的 out 的轴映射到 ABC 的轴; “jiki->ijk”表示轴 0(“j”)映射到轴 1,轴 1 和轴 3(“i”)映射到轴 0,轴 2(“k”)映射到轴 2。 将两个轴映射到一个轴(如“i”)具有采用对角线的特殊含义。

einsum 创建一个可写 View ,所以剩下要做的就是将 ABC 分配给它。

注意:我们对形状和 einsum 规范使用相同的字母 i、j、k 在句法上没有任何意义,它只是使内容更具可读性。