Python 两个numpy数组的每行组合的串联

Python 两个numpy数组的每行组合的串联,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,给定两个不同形状的数组(A和B),我想生成一个数组,其中包含A中的每一行与B中的每一行的串联 例如: A = np.array([[1, 2], [3, 4], [5, 6]]) B = np.array([[7, 8, 9], [10, 11, 12]]) 要生成阵列,请执行以下操作: [[1, 2, 7, 8, 9], [1, 2, 10, 11, 12], [3, 4, 7, 8, 9], [3,

给定两个不同形状的数组(A和B),我想生成一个数组,其中包含A中的每一行与B中的每一行的串联

例如:

A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

B = np.array([[7, 8, 9],
              [10, 11, 12]])
要生成阵列,请执行以下操作:

[[1, 2, 7, 8, 9],
 [1, 2, 10, 11, 12],
 [3, 4, 7, 8, 9],
 [3, 4, 10, 11, 12],
 [5, 6, 7, 8, 9],
 [5, 6, 10, 11, 12]]
我可以通过迭代来实现这一点,但它非常慢,因此需要寻找一些组合的
numpy
函数来尽可能高效地重新创建上述内容(输入数组A和B的大小将达到10000行,因此需要避免嵌套循环)

参考:

输出:

[array([1, 2, 7, 8, 9]),
 array([ 1,  2, 10, 11, 12]),
 array([3, 4, 7, 8, 9]),
 array([ 3,  4, 10, 11, 12]),
 array([5, 6, 7, 8, 9]),
 array([ 5,  6, 10, 11, 12])]

完美的问题,了解和

这是一个使用这些工具的矢量化解决方案-

def concatenate_per_row(A, B):
    m1,n1 = A.shape
    m2,n2 = B.shape

    out = np.zeros((m1,m2,n1+n2),dtype=A.dtype)
    out[:,:,:n1] = A[:,None,:]
    out[:,:,n1:] = B
    return out.reshape(m1*m2,-1)
样本运行-

In [441]: A
Out[441]: 
array([[1, 2],
       [3, 4],
       [5, 6]])

In [442]: B
Out[442]: 
array([[ 7,  8,  9],
       [10, 11, 12]])

In [443]: concatenate_per_row(A, B)
Out[443]: 
array([[ 1,  2,  7,  8,  9],
       [ 1,  2, 10, 11, 12],
       [ 3,  4,  7,  8,  9],
       [ 3,  4, 10, 11, 12],
       [ 5,  6,  7,  8,  9],
       [ 5,  6, 10, 11, 12]])

真漂亮!谢谢,它工作得很好,并且有预先分配输出数组的附带好处,因此可以确保我在前面有足够的空间。@DaveChallis这就是整个想法。对于大型阵列,任何堆叠操作都只是内存/性能效率方面的惩罚。@Divakar,漂亮的解决方案!如果您有时间,您能给我一个提示,如何使用broadcast_to函数来强制显式广播concatenate。在上有一个讨论,但它都是基于希望加入(n,1)数组而不是整行,并且它实际上不使用广播来连接。例如,我很难适应一个数组是(3,3),另一个是(4,2)的情况[寻找形状(12,5)的答案]。您的解决方案在这方面是有效的,但希望更好地掌握broadcast_to()。
In [441]: A
Out[441]: 
array([[1, 2],
       [3, 4],
       [5, 6]])

In [442]: B
Out[442]: 
array([[ 7,  8,  9],
       [10, 11, 12]])

In [443]: concatenate_per_row(A, B)
Out[443]: 
array([[ 1,  2,  7,  8,  9],
       [ 1,  2, 10, 11, 12],
       [ 3,  4,  7,  8,  9],
       [ 3,  4, 10, 11, 12],
       [ 5,  6,  7,  8,  9],
       [ 5,  6, 10, 11, 12]])