2014-02-17 15 views
5

我有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这么多(反之亦然)。

回答

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 
+0

第二个结果给出了不同的结果,你可以看到 – Claudiu

+0

'a [:,None] - b' – M4rtini

+0

@ M4rtini:哦,那样更好;谢谢。 – unutbu

0

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

np.vstack(a)-b 

不过,我喜欢这一个,因为它是非常短的。

此外,它也可以工作,如果ab是基本的Python列表(不像上面注释中非常方便的a[:, None] - b)。