4

I have two Numpy arrays x with shape (m, i) and y with shape (m, j) (so the number of rows is the same). I would like to multiply each column of x with each column of y element-wise so that the result is of shape (m, i*j).

Example:

import numpy as np

np.random.seed(1)
x = np.random.randint(0, 2, (10, 3))
y = np.random.randint(0, 2, (10, 2))

This creates the following two arrays x:

array([[1, 1, 0],
       [0, 1, 1],
       [1, 1, 1],
       [0, 0, 1],
       [0, 1, 1],
       [0, 0, 1],
       [0, 0, 0],
       [1, 0, 0],
       [1, 0, 0],
       [0, 1, 0]])

and y:

array([[0, 0],
       [1, 1],
       [1, 1],
       [1, 0],
       [0, 0],
       [1, 1],
       [1, 1],
       [1, 1],
       [0, 1],
       [1, 0]])

Now the result should be:

array([[0, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 1],
       [0, 0, 0, 0, 0, 0],
       [1, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0]])

Currently, I've implemented this operation with two nested loops over the columns of x and y:

def _mult(x, y):
    r = []
    for xc in x.T:
        for yc in y.T:
            r.append(xc * yc)
    return np.array(r).T

However, I'm pretty sure that there must be a more elegant solution that I can't seem to come up with.

1 Answer 1

7

Use NumPy broadcasting -

(y[:,None]*x[...,None]).reshape(x.shape[0],-1)

Explanation

As inputs, we have -

y : 10 x 2
x : 10 x 3

With y[:,None], we are introducing a new axis between the existing two dims, thus creating a 3D array version of it. This keeps the first axis as the first one in 3D version and pushes out the second axis as the third one.

With x[...,None], we are introducing a new axis as the last one by pushing up the two existing dims as the first two dims to result in a 3D array version.

To summarize, with the introduction of new axes, we have -

y : 10 x 1 x 2
x : 10 x 3 x 1

With y[:,None]*x[...,None], there would be broadcasting for both y and x, resulting in an output array with a shape of (10,3,2). To get to the final output array of shape (10,6), we just need to merge the last two axes with that reshape.

Sign up to request clarification or add additional context in comments.

3 Comments

"complicated" hack but very concise! +1
can you add some explanation here? it's concise but not explanatory.
@kmario23 Added some explanation, check it out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.