Reputation: 15
I would like to compute:
matrix1 + vector * matrix2
where:
In: matrix1.shape
Out: (3, 3)
In: vector.shape
Out: (15,)
In: matrix2.shape
Out: (3, 3)
I did it this way:
answer = []
for i in vector:
answer_i = matrix1 + i * matrix2
answer.append(answer_i)
So, I get a list of len(vector) in which each answer is shape (3,3). I wonder how to do the exact same thing, but without "for" loop and with NumPy arrays. The answer would be an array of shape (3, 3, 15). The answer may be simple but I don't have a lot of experience.
For example:
In: matrix1
Out: array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In: vector
Out: array([-7., -6., -5., -4., -3., -2., -1., 0., 1., 2., 3., 4., 5., 6., 7.])
In: matrix2
Out: array([[ 5, 5, 5],
[10, 10, 10],
[20, 20, 20]])
My output (a list of len 15 for now):
[array([[ -34., -33., -32.],
[ -66., -65., -64.],
[-133., -132., -131.]]),
array([[ -29., -28., -27.],
[ -56., -55., -54.],
[-113., -112., -111.]]),
array([[-24., -23., -22.],
[-46., -45., -44.],
[-93., -92., -91.]]),
array([[-19., -18., -17.],
[-36., -35., -34.],
[-73., -72., -71.]]),
array([[-14., -13., -12.],
[-26., -25., -24.],
[-53., -52., -51.]]),
array([[ -9., -8., -7.],
[-16., -15., -14.],
[-33., -32., -31.]]),
array([[ -4., -3., -2.],
[ -6., -5., -4.],
[-13., -12., -11.]]),
array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]]),
array([[ 6., 7., 8.],
[14., 15., 16.],
[27., 28., 29.]]),
array([[11., 12., 13.],
[24., 25., 26.],
[47., 48., 49.]]),
array([[16., 17., 18.],
[34., 35., 36.],
[67., 68., 69.]]),
array([[21., 22., 23.],
[44., 45., 46.],
[87., 88., 89.]]),
array([[ 26., 27., 28.],
[ 54., 55., 56.],
[107., 108., 109.]]),
array([[ 31., 32., 33.],
[ 64., 65., 66.],
[127., 128., 129.]]),
array([[ 36., 37., 38.],
[ 74., 75., 76.],
[147., 148., 149.]])]
I would like the output to be an array of shape (3, 3, 15).
Upvotes: 0
Views: 242
Reputation: 36249
You can just insert an extra dimension into the matrices and NumPy broadcasting will do the rest:
matrix1[..., None] + vector*matrix2[..., None]
Upvotes: 1
Reputation: 231395
In [1]: m1 = np.arange(1,10).reshape(3,3)
In [2]: vector = np.array([-7., -6., -5., -4., -3., -2., -1., 0., 1., 2., 3.
...: , 4., 5., 6., 7.])
In [4]: m2 = np.array([5,10,20])[:,None]+np.zeros(3,int)
In [5]: m2
Out[5]:
array([[ 5, 5, 5],
[10, 10, 10],
[20, 20, 20]])
In [6]: vector.shape
Out[6]: (15,)
np.array(answer)
will produce a (15,3,3) array. With numpy
broadcasting, we can get the same with:
In [12]: (m1+vector[:,None,None]*m2)
Out[12]:
array([[[ -34., -33., -32.],
[ -66., -65., -64.],
[-133., -132., -131.]],
[[ -29., -28., -27.],
[ -56., -55., -54.],
[-113., -112., -111.]],
...
[[ 36., 37., 38.],
[ 74., 75., 76.],
[ 147., 148., 149.]]])
vector
becomes (15,1,1) and the m's
(1,3,3) to match, together making (15,3,3).
But if you want the (15,) vector
dimension to be last we need to do:
In [13]: (m1[:,:,None]+vector*m2[:,:,None])
Out[13]:
array([[[ -34., -29., -24., -19., -14., -9., -4., 1., 6.,
11., 16., 21., 26., 31., 36.],
[ -33., -28., -23., -18., -13., -8., -3., 2., 7.,
12., 17., 22., 27., 32., 37.],
[ -32., -27., -22., -17., -12., -7., -2., 3., 8.,
13., 18., 23., 28., 33., 38.]],
...
[-131., -111., -91., -71., -51., -31., -11., 9., 29.,
49., 69., 89., 109., 129., 149.]]])
Here the broadcasting is (3,3,1) with (15,) => (3,3,15)
We could have also applied a transpose to the first case, changing the (15,3,3) shape to (3,3,15):
(m1+vector[:,None,None]*m2).transpose(1,2,0)
Another way is to join the 15 arrays on a new last axis.
np.stack(answer, axis=2)
Upvotes: 1