Reputation: 883
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?
Upvotes: 0
Views: 1187
Reputation: 221584
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
Upvotes: 2
Reputation: 114330
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.
Upvotes: 1
Reputation: 231385
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])
Upvotes: 2