合并或加入numpy数组

时间:2016-04-02 01:39:01

标签: python arrays performance numpy vectorization

我如何加入两个numpy ndarray来快速完成以下任务,使用优化的numpy,没有任何循环?

>>> a = np.random.rand(2,2)
>>> a
array([[ 0.09028802,  0.2274419 ],
       [ 0.35402772,  0.87834376]])

>>> b = np.random.rand(2,2)
>>> b
array([[ 0.4776325 ,  0.73690098],
       [ 0.69181444,  0.672248  ]])

>>> c = ???
>>> c
array([[ 0.09028802,  0.2274419, 0.4776325 ,  0.73690098],
       [ 0.09028802,  0.2274419, 0.69181444,  0.672248  ],
       [ 0.35402772,  0.87834376, 0.4776325 ,  0.73690098],
       [ 0.35402772,  0.87834376, 0.69181444,  0.672248  ]])

6 个答案:

答案 0 :(得分:3)

显然,你想要的是水平叠放的ab的笛卡尔积。您可以使用itertools模块为numpy数组生成索引,然后使用numpy.hstack来堆叠它们:

import numpy as np
from itertools import product

a = np.array([[ 0.09028802,  0.2274419 ],
              [ 0.35402772,  0.87834376]])

b = np.array([[ 0.4776325 ,  0.73690098],
              [ 0.69181444,  0.672248  ],
              [ 0.79941110,  0.52273   ]])

a_inds, b_inds = map(list, zip(*product(range(len(a)), range(len(b)))))

c = np.hstack((a[a_inds], b[b_inds]))

这导致c

array([[ 0.09028802,  0.2274419 ,  0.4776325 ,  0.73690098],
       [ 0.09028802,  0.2274419 ,  0.69181444,  0.672248  ],
       [ 0.09028802,  0.2274419 ,  0.7994111 ,  0.52273   ],
       [ 0.35402772,  0.87834376,  0.4776325 ,  0.73690098],
       [ 0.35402772,  0.87834376,  0.69181444,  0.672248  ],
       [ 0.35402772,  0.87834376,  0.7994111 ,  0.52273   ]])

打破指数的事情:

如果您将其转换为列表,

product(range(len(a)), range(len(b))将生成如下所示的内容:

[(0, 0), (0, 1), (1, 0), (1, 1)]

你想要这样的东西:[0, 0, 1, 1][0, 1, 0, 1],所以你需要转置生成器。执行此操作的惯用方法是使用zip(*zipped_thing)。但是,如果您只是直接分配这些内容,那么您将获得tuples,如下所示:

[(0, 0, 1, 1), (0, 1, 0, 1)]

但是numpy数组将元组解释为多维索引,因此您希望将它们转换为列表,这就是我将list构造函数映射到product函数的结果的原因。

答案 1 :(得分:3)

不是最漂亮,但您可以合并hstackrepeattile

>>> a = np.arange(4).reshape(2,2)
>>> b = a+10
>>> a
array([[0, 1],
       [2, 3]])
>>> b
array([[10, 11],
       [12, 13]])
>>> np.hstack([np.repeat(a,len(a),0),np.tile(b,(len(b),1))])
array([[ 0,  1, 10, 11],
       [ 0,  1, 12, 13],
       [ 2,  3, 10, 11],
       [ 2,  3, 12, 13]])

或3x3案例:

>>> a = np.arange(9).reshape(3,3)
>>> b = a+10
>>> np.hstack([np.repeat(a,len(a),0),np.tile(b,(len(b),1))])
array([[ 0,  1,  2, 10, 11, 12],
       [ 0,  1,  2, 13, 14, 15],
       [ 0,  1,  2, 16, 17, 18],
       [ 3,  4,  5, 10, 11, 12],
       [ 3,  4,  5, 13, 14, 15],
       [ 3,  4,  5, 16, 17, 18],
       [ 6,  7,  8, 10, 11, 12],
       [ 6,  7,  8, 13, 14, 15],
       [ 6,  7,  8, 16, 17, 18]])

答案 2 :(得分:2)

让我们通过一个预期的解决方案来处理涉及不同形状数组的一般情况,并使用一些内联注释来解释所涉及的方法。

(1)首先,我们存储输入数组的形状。

ma,na = a.shape
mb,nb = b.shape

(2)接下来,初始化一个3D数组,其列数是输入数组ab中列数的总和。使用np.empty执行此任务。

out = np.empty((ma,mb,na+nb),dtype=a.dtype)

(3)然后,使用aa[:,None,:]的行为第一个“na”列设置3D数组的第一个轴。因此,如果我们将它分配给out[:,:,:na],那么第二个冒号将向NumPy表明我们需要一个广播设置,如果可能的话,NumPy数组中的单例dims总是会发生。实际上,这与平铺/重复相同,但可能是有效的方式。

out[:,:,:na] = a[:,None,:]

(4)重复将b中的元素设置为输出数组。这次我们将沿着out的第一个轴与out[:,:,na:]进行广播,第一个冒号帮助我们进行广播。

out[:,:,na:] = b

(5)最后一步是将输出重新整形为2D形状。这可以通过简单地用所需的2D形状元组改变形状来完成。重塑仅改变视图,实际上是零成本。

out.shape = (ma*mb,na+nb)

冷凝所有内容,完整的实现将如下所示 -

ma,na = a.shape
mb,nb = b.shape
out = np.empty((ma,mb,na+nb),dtype=a.dtype)
out[:,:,:na] = a[:,None,:]
out[:,:,na:] = b
out.shape = (ma*mb,na+nb)

答案 3 :(得分:0)

您可以使用dstack()broadcast_arrays()

import numpy as np

a = np.random.randint(0, 10, (3, 2))
b = np.random.randint(10, 20, (4, 2))

np.dstack(np.broadcast_arrays(a[:, None], b)).reshape(-1, a.shape[-1] + b.shape[-1])

答案 4 :(得分:0)

尝试使用np.hstack或np.vstack。即使长度不相同的数组也可以使用。您需要做的就是: np.hstack(appendedarray [:])或np.vstack(appendedarray [:])

答案 5 :(得分:-1)

所有数组都是可索引的,因此您只需调用:

即可合并
a[:2],b[:2]

或者您可以使用核心numpy堆叠功能,应该看起来像这样:

c = np.vstack(a,b)