如何有效地将操作符应用于两个数组的笛卡尔积?

时间:2014-02-17 22:35:44

标签: python arrays performance numpy

我有a = array([1, 2, 3, 4, 5])b = array([10, 20, 30, 40, 50])。我想要:

array([[ -9, -19, -29, -39, -49],
       [ -8, -18, -28, -38, -48],
       [ -7, -17, -27, -37, -47],
       [ -6, -16, -26, -36, -46],
       [ -5, -15, -25, -35, -45]])

最有效的方法是什么?我有

np.transpose([a]) - np.tile(b, (len(a), 1))

但是我想知道如果a非常大,是否有更有效的方式,这不需要复制b那么多(反之亦然)。

2 个答案:

答案 0 :(得分:10)

某些NumPy功能,例如np.subtractnp.addnp.multiplynp.dividenp.logical_andnp.bitwise_and等,具有“外部功能“可用于创建等效”乘法表“的方法:

In [76]: np.subtract.outer(a, b)
Out[76]: 
array([[ -9, -19, -29, -39, -49],
       [ -8, -18, -28, -38, -48],
       [ -7, -17, -27, -37, -47],
       [ -6, -16, -26, -36, -46],
       [ -5, -15, -25, -35, -45]])

或使用广播:

In [96]: a[:, None] - b
Out[96]: 
array([[ -9, -19, -29, -39, -49],
       [ -8, -18, -28, -38, -48],
       [ -7, -17, -27, -37, -47],
       [ -6, -16, -26, -36, -46],
       [ -5, -15, -25, -35, -45]])

两者的表现大致相同:

In [98]: a = np.tile(a, 1000)

In [99]: b = np.tile(b, 1000)

In [100]: %timeit a[:, None] - b
10 loops, best of 3: 88.3 ms per loop

In [101]: %timeit np.subtract.outer(a, b)
10 loops, best of 3: 87.8 ms per loop

In [102]: %timeit np.transpose([a]) - np.tile(b, (len(a), 1))
10 loops, best of 3: 120 ms per loop

答案 1 :(得分:0)

您也可以使用np.vstack进行广播,但在其他答案之后没有任何新想法:

np.vstack(a)-b

但我喜欢这个,因为它很短。

此外,如果ab是基本的Python列表(与上面评论中非常方便的a[:, None] - b不同),它也有效。