Karnivaurus
Karnivaurus

Reputation: 24151

Elementwise multiplication of numpy matrix and column array

Using numpy, I want to multiple a matrix x by a column array y, elementwise:

   x = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
   y = numpy.array([1, 2, 3])
   z = numpy.multiply(x, y)
   print z

This gives the output as if y is a row array:

   [[ 1  4  9]
    [ 4 10 18]
    [ 7 16 27]]

However, I want the output as if y is a column array:

   [[ 1  2  3]
    [ 8 10 12]
    [21 24 27]]

So how can I manipulate y to achieve this? If I use:

y = numpy.transpose(y)

then y remains the same shape.

Upvotes: 2

Views: 3626

Answers (4)

Roger Fan
Roger Fan

Reputation: 5045

The reason you can't transpose y is because it's initialized as a 1-D array. Transposing an array only makes sense in two (or more) dimensions.

To get around these mixed-dimension issues, numpy actually provides a set of convenience functions to sanitize your inputs:

y = np.array([1, 2, 3])
y1 = np.atleast_1d(y)  # Converts array to 1-D if less than that
y2 = np.atleast_2d(y)  # Converts array to 2-D if less than that
y3 = np.atleast_3d(y)  # Converts array to 3-D if less than that

I also think np.column_stack falls under this convenience category, as it puts together 1-D and 2-D arrays as columns like you would expect, rather than having to figure out the right series of reshapes and stacks.

y1 = np.array([1, 2, 3])
y2 = np.array([2, 4, 6])
y3 = np.array([[2, 6], [2, 4], [7, 7]])
y = np.column_stack((y1, y2, y3))

I think these functions aren't as well known as they should be, and I find them much easier, more flexible, and safer than manually fiddling with reshape or array dimensions. They also avoid making copies when possible, which can be a small performance speedup.


To answer your question, you should use np.atleast_2d to convert your array to a 2-D array, then transpose it.

y = np.atleast_2d(y).T    

The other way to quickly do it without worrying about y is to transpose x then transpose the result back.

z = (x.T * y).T

Though this can obfuscate the intent of the code. It is probably faster though if performance is important.


If performance is important, that can inform which method you want to use. Some timings on my computer:

%timeit x * np.atleast_2d(y).T
100000 loops, best of 3: 7.98 us per loop

%timeit (x.T*y).T
100000 loops, best of 3: 3.27 us per loop

%timeit x * np.transpose([y])
10000 loops, best of 3: 20.2 us per loop

%timeit x * y.reshape(-1, 1)
100000 loops, best of 3: 3.66 us per loop

Upvotes: 2

Lukeclh
Lukeclh

Reputation: 231

The y variable has a shape of (3,). If you construct it this way:

y = numpy.array([1, 2, 3], ndmin=2)

...it will have a shape of (1,3), which you can transpose to get the result you want:

y = numpy.array([1, 2, 3], ndmin=2).T z = numpy.multiply(x, y)

Upvotes: 0

Ben
Ben

Reputation: 2143

Enclose it in another list to make it 2D:

>>> y2 = numpy.transpose([y])
>>> y2
array([[1],
       [2],
       [3]])
>>> numpy.multiply(x, y2)
array([[ 1,  2,  3],
       [ 8, 10, 12],
       [21, 24, 27]])

Upvotes: 2

Daniel
Daniel

Reputation: 42778

You can use reshape:

y = y.reshape(-1,1)

Upvotes: 1

Related Questions