numpy dot product of sub array?

1k Views Asked by At

I have two ndarray like

n1 = np.array([1,2,3,4])
n2 = np.array([1,2,3,4])

While dot product of them can done easily with np.dot(n1, n2), which gives 30 as the right answer. What if I need the dot to be operated on two subarrays from n1 and n2, e.g.

np.dot(np.array([1,2]), np.array([1,2]))  # first two elements from arrays
np.dot(np.array([3,4]), np.array([3,4]))  # last two elements

Gives [5, 25]. I could do it by hand split array and for loop. But wondering if there is a more pythonic and numpy way to do this?

3

There are 3 best solutions below

0
On BEST ANSWER

Here's one way:

In [124]: n1 = np.array([1,2,3,4])
     ...: n2 = np.array([1,2,3,4])
     ...: 

reshaping splits the arrays in to the desired blocks:

In [125]: n1.reshape(2,2)
Out[125]: 
array([[1, 2],
       [3, 4]])

now multiply all elements together - and sum on the right axis (sometimes I guess as to axis).

In [126]: (n1.reshape(2,2)*n2.reshape(2,2)).sum(axis=1)
Out[126]: array([ 5, 25])

That sum of products can also be expressed with einsum - but don't worry if the syntax is too new:

In [127]: np.einsum('ij,ij->i',n1.reshape(2,2), n2.reshape(2,2))
Out[127]: array([ 5, 25])
1
On

Reshape to have two two column arrays, since we want subarrays of length 2 each and then use np.einsum for the sum-reduction -

a = n1.reshape(-1,2)
b = n2.reshape(-1,2)

out = np.einsum('ij,ij->i',a,b)

Another one would be to do element-wise multiplication, then use one reshape and finally sum each row for a compact solution -

out = (n1*n2).reshape(-1,2).sum(1) # 2 is subarray length
3
On

You can perform the dot by manually multiplying and adding the arrays. If you use np.add's reduceat method, you have the flexibility of summing over completely arbitrary intervals:

n = np.add.reduceat(n1 * n2, [0, 2])

If you wanted to have the sum over the first three and the last one element, you would just pass [0, 3] for the indices (the second argument).

If arbitrary length intervals are not interesting to you, use the other answers instead.