简体   繁体   中英

How to multiply a numpy tuple array by scalar array

I have a numpy array A of shape(N,2) and a numpy array S of shape(N).

How do I multiply both arrays? Currently I am using this code:

tupleS = numpy.zeros( (N , 2) )
tupleS[:,0] = S
tupleS[:,1] = S
product = A * tupleS

I am a python beginner. Is there a better way to do this?

Numpy uses row-major order, so you have to explicitly create a column. As in:

>> A = numpy.array(range(10)).reshape(5, 2)
>>> B = numpy.array(range(5))
>>> B
array([0, 1, 2, 3, 4])
>>> A * B
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: shape mismatch: objects cannot be broadcast to a single shape
>>> B = B.reshape(5, 1)
>>> B
array([[0],
       [1],
       [2],
       [3],
       [4]])
>>> A * B
array([[ 0,  0],
       [ 2,  3],
       [ 8, 10],
       [18, 21],
       [32, 36]])

Essentially the same as @senderle's answer, but does not require an in-place manipulation of S. You can get a slice an array in a way that adds axes with the index None and this will multiply them: A * S[:,None] .

>>> S = np.arange(5)
>>> S
array([0, 1, 2, 3, 4])
>>> A = np.arange(10).reshape((5,2))
>>> A
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7],
       [8, 9]])
>>> S[:,None]
array([[0],
       [1],
       [2],
       [3],
       [4]])
>>> A * S[:,None]
array([[ 0,  0],
       [ 2,  3],
       [ 8, 10],
       [18, 21],
       [32, 36]])

Have you tried this:

product = A * S

Al tough the title of your question is slightly misnomer, I think the problem you have encountered is mainly related on the numpy broadcasting rules . Thus the following will not work (as you already have observed):

In []: N= 5
In []: A= rand(N, 2)
In []: A.shape
Out[]: (5, 2)

In []: S= rand(N)
In []: S.shape
Out[]: (5,)

In []: A* S
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (5,2) (5) 

However, now a simple way to make S compatible with broadcasting rules (of element wise product of A* S ), is to expand its dimension, like:

In []: A* S[:, None]
Out[]: 
array([[ 0.54216549,  0.04964989],
       [ 0.41850647,  0.4197221 ],
       [ 0.03790031,  0.76744563],
       [ 0.29381325,  0.53480765],
       [ 0.0646535 ,  0.07367852]])

But this is really nothing but syntactical sugar forexpand_dims , like:

In []: expand_dims(S, 1).shape
Out[]: (5, 1)

Anyway, I personally prefer this simple hassle free approach:

In []: S= rand(N, 1)
In []: S.shape
Out[]: (5, 1)

In []: A* S
Out[]: 
array([[ 0.40421854,  0.03701712],
       [ 0.63891595,  0.64077179],
       [ 0.03117081,  0.63117954],
       [ 0.24695035,  0.44950641],
       [ 0.14191946,  0.16173008]])

Thus with python ; it's more straightforward to be explicit than implicit.

I can think of:

product = A * numpy.tile(S, (2,1)).T

A faster solution might be:

product = [d * S for d in A.T]

though that doesn't get you a numpy array as output, and it's transposed. So to get a similar numpy array (note that this is slower than the first solution):

product = numpy.array([d * S for d in A.T]).T

There's probably a dozen other valid solutions, including better ones than these...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM