Home > Back-end >  Numpy: Apply function pairwise on two arrays of different length
Numpy: Apply function pairwise on two arrays of different length

Time:10-26

I am trying to make use of numpy vectorized operations. But I struggle on the following task: The setting is two arrays of different length (X1, X2). I want to apply a method to each pair (e.g. X1[0] with X2[0], X2[1], etc). I wrote the following working code using loops, but I'd like to get rid of the loops.

result = []
for i in range(len(X1)):
    result.append([])
    for j in range(len(X2)):
        tmp = my_method(X1[i] - X2[j])
        result[i].append(tmp)
result = np.asarray(result)

CodePudding user response:

You can reshape one of your vectors to be (N, 1) and then use vectorize which will broadcast the operation as normal:

import numpy as np

X1 = np.arange(5)
X2 = np.arange(3)
print(X1, X2)
# [0 1 2 3 4] [0 1 2]

def my_op(x, y):
  return x   y

np.vectorize(my_op)(X1[:, np.newaxis], X2)
# array([[0, 1, 2],
#        [1, 2, 3],
#        [2, 3, 4],
#        [3, 4, 5],
#        [4, 5, 6]])

Note that my_op is just defined as an example; if your function is actually anything included in numpy's vectorized operations, it'd be much faster to just use that directly, e.g.:

X1[:, np.newaxis]   X2

CodePudding user response:

itertools.product might be what you're looking for:

from itertools import product
import numpy as np

x1 = np.array(...)
x2 = np.array(...)
result = np.array([my_method(x_1 - x_2) for x_1, x_2 in product(x1,x2)])

Alternatively you could also use a double list comprehension:

result = np.array([my_method(x_1 - x_2) for x_1 in x1 for x_2 in x2])

This obviously depends on what my_method is doing and operating on and what you have stored in x1 and x2.

CodePudding user response:

Assuming a simple function my_method(a, b), which adds the two numbers.

And this input:

X1 = np.arange(10)
X2 = np.arange(10,60,10)

You code is:

result = []
for i in range(len(X1)):
    result.append([])
    for j in range(len(X2)):
        tmp = my_method(X1[i], X2[j])
        result[i].append(tmp)
result = np.asarray(result)

You can replace it with broadcasting:

X1[:,None] X2

output:

array([[10, 20, 30, 40, 50],
       [11, 21, 31, 41, 51],
       [12, 22, 32, 42, 52],
       [13, 23, 33, 43, 53],
       [14, 24, 34, 44, 54],
       [15, 25, 35, 45, 55],
       [16, 26, 36, 46, 56],
       [17, 27, 37, 47, 57],
       [18, 28, 38, 48, 58],
       [19, 29, 39, 49, 59]])

Now you need to see if your operation can be vectorized… please share details on what you want to achieve. Functions can be vectorized using numpy.vectorize, but this is not a magic tool as it will loop on the elements, which can be slow. The best is to have a true vector operation.

  • Related