Reputation: 61
I am worrying that this might be a really stupid question. However I can't find a solution. I want to do the following operation in python without using a loop, because I am dealing with large size arrays. Is there any suggestion?
import numpy as np
a = np.array([1,2,3,..., N]) # arbitrary 1d array
b = np.array([[1,2,3],[4,5,6],[7,8,9]]) # arbitrary 2d array
c = np.zeros((N,3,3))
c[0,:,:] = a[0]*b
c[1,:,:] = a[1]*b
c[2,:,:] = a[2]*b
c[3,:,:] = ...
...
...
c[N-1,:,:] = a[N-1]*b
Upvotes: 3
Views: 1723
Reputation: 7504
What you're doing is an outer product. This operator is available in numpy as multiply.outer
:
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
c = np.multiply.outer(a, b)
print(c)
[[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]]
[[ 2 4 6]
[ 8 10 12]
[14 16 18]]
[[ 3 6 9]
[12 15 18]
[21 24 27]]
[[ 4 8 12]
[16 20 24]
[28 32 36]]
[[ 5 10 15]
[20 25 30]
[35 40 45]]]
multiply
is a ufunc. According to the documentation of ufunc.outer: "Apply the ufunc op to all pairs (a, b) with a in A and b in B" (here that means applying the multiply operator). Still according to the documentation, doing this is equivalent to:
r = empty(len(A),len(B))
for i in range(len(A)):
for j in range(len(B)):
r[i,j] = op(A[i], B[j]) # op = ufunc in question
Upvotes: 0
Reputation: 25023
My answer uses only numpy
primitives, in particular for the array multiplication (what you want to do has a name, it is an outer product).
Due to a restriction in numpy
's outer multiplication function we have to reshape the result, but this is very cheap because the data block of the ndarray
is not involved.
% python
Python 2.7.8 (default, Oct 18 2014, 12:50:18)
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> a = np.array((1,2))
>>> b = np.array([[n*m for m in (1,2,3,4,5,6)] for n in (10,100,1000)])
>>> print b
[[ 10 20 30 40 50 60]
[ 100 200 300 400 500 600]
[1000 2000 3000 4000 5000 6000]]
>>> print np.outer(a,b)
[[ 10 20 30 40 50 60 100 200 300 400 500 600
1000 2000 3000 4000 5000 6000]
[ 20 40 60 80 100 120 200 400 600 800 1000 1200
2000 4000 6000 8000 10000 12000]]
>>> print "Almost there!"
Almost there!
>>> print np.outer(a,b).reshape(a.shape[0],b.shape[0], b.shape[1])
[[[ 10 20 30 40 50 60]
[ 100 200 300 400 500 600]
[ 1000 2000 3000 4000 5000 6000]]
[[ 20 40 60 80 100 120]
[ 200 400 600 800 1000 1200]
[ 2000 4000 6000 8000 10000 12000]]]
>>>
Upvotes: 2
Reputation: 353069
To avoid Python-level loops, you could use np.newaxis
to expand a
(or None, which is the same thing):
>>> a = np.arange(1,5)
>>> b = np.arange(1,10).reshape((3,3))
>>> a[:,None,None]*b
array([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]],
[[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]],
[[ 3, 6, 9],
[12, 15, 18],
[21, 24, 27]],
[[ 4, 8, 12],
[16, 20, 24],
[28, 32, 36]]])
Or np.einsum
, which is overkill here, but is often handy and makes it very explicit what you want to happen with the coordinates:
>>> c2 = np.einsum('i,jk->ijk', a, b)
>>> np.allclose(c2, a[:,None,None]*b)
True
Upvotes: 1
Reputation: 6680
Didn't understand this multiplication.. but here is a way to make matrix multiplication in python using numpy:
import numpy as np
a = np.matrix([1, 2])
b = np.matrix([[1, 2], [3, 4]])
result = a*b
print(result)
>>>result
matrix([7, 10])
Upvotes: 0