Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to efficiently apply an operator to the cartesian product of two arrays?

I have a = array([1, 2, 3, 4, 5]) and b = array([10, 20, 30, 40, 50]). I want:

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]])

What's the most efficient way to do this? I have

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

However I wonder if there's a more efficient way than this if a is very large, which wouldn't require copying b so much (or vice versa).

like image 559
Claudiu Avatar asked Feb 17 '14 22:02

Claudiu


1 Answers

Some NumPy functions, like np.subtract, np.add, np.multiply, np.divide, np.logical_and, np.bitwise_and, etc. have an "outer" method which can be used to create the equivalent of "multiplication tables":

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]])

or, using broadcasting:

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]])

The performance of the two is about the same:

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
like image 132
unutbu Avatar answered Nov 14 '22 21:11

unutbu