4

I've got two 2D numpy arrays called A and B, where A is M x N and B is M x n. My problem is that I wish to multiply each element of each row of B with corresponding row of A and create a 3D matrix C which is of size M x n x N, without using for-loops.

As an example, if A is:

A = np.array([[1, 2, 3],
              [4, 5, 6]])

and B is

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

Then the resulting multiplication C = A x B would look something like

C = [
     [[1, 2],
      [12, 16]],
     [[2, 4],
      [15, 20]],
     [[3, 6],
      [18, 24]]
     ]

Is it clear what I'm trying to achieve, and is it possible doing without any for-loops? Best, tingis

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
Tingiskhan
  • 1,305
  • 3
  • 16
  • 29

2 Answers2

6

You can use the NumPy Einstein summation function, einsum():

C=np.einsum('ij,ik->jik',A,B)
swimfar2
  • 103
  • 8
yevgeniy
  • 888
  • 7
  • 14
  • 1
    Thanks for the quick answer! This funcition helps a lot, will go with your solution! – Tingiskhan Aug 20 '15 at 12:01
  • `einsum` can do wondrous things, i think it is also faster than other numpy vector product methods. Also, by changing the index order after ->, you can do a reshape without an extra call to the actual `reshape`. – yevgeniy Aug 20 '15 at 12:09
  • 2
    @yevgeniy about being faster, [It depends on the size of the array](http://stackoverflow.com/a/30645430/832621). Usually it is faster for smaller arrays, while for larger arrays I measured speeds comparable to the method using `newaxis` – Saullo G. P. Castro Aug 20 '15 at 12:12
  • 2
    @SaulloCastro. Thanks for running an actual test. I was also following [this](http://stackoverflow.com/questions/32083997/huge-speed-difference-in-numpy-between-similar-code), where `einsum` really showed great performance, so it seems at array size >10000 is where one should consider alternative solutions. – yevgeniy Aug 20 '15 at 12:26
4

It is possible by creating a new axis in each array and transposing the modified A:

A[np.newaxis,...].T * B[np.newaxis,...]

giving:

array([[[ 1,  2],
        [12, 16]],

       [[ 2,  4],
        [15, 20]],

       [[ 3,  6],
        [18, 24]]])
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234