Reputation: 5384
I just ended up being confused about this for a while, so I thought I'd document in Q&A format - although more thorough explanations are more than welcome.
Let's say, I have a 2D numpy array, say xm
below:
$ python3
Python 3.8.9 (default, Apr 3 2021, 09:30:04) [GCC 10.2.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
import numpy as np
x = y = np.linspace(0,1.0, 4)
xm,ym = np.meshgrid(x,y)
xm
array([[0. , 0.33333333, 0.66666667, 1. ],
[0. , 0.33333333, 0.66666667, 1. ],
[0. , 0.33333333, 0.66666667, 1. ],
[0. , 0.33333333, 0.66666667, 1. ]])
>>>
... and I want to replace each element, with an array of 3 elements - say, with: the basis [1.0, 1.0, 0.5], multiplied by the scalar value of each element of the 2D array.
Multiplication of a numpy array with a scalar is trivial:
xm*2
array([[0. , 0.66666667, 1.33333333, 2. ],
[0. , 0.66666667, 1.33333333, 2. ],
[0. , 0.66666667, 1.33333333, 2. ],
[0. , 0.66666667, 1.33333333, 2. ]])
... but attempting to do "scalar (element od 2D array) times list" trivially does not work:
xm*np.array([1,1])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,4) (2,)
... and trying to cheat by iterating through all the elements of the 2D array, and replacing each with a list/array, also fails:
for ir, irow in enumerate(xm):
for ic, icol in enumerate(irow):
xm[ir][ic] = icol*np.array([1, 1, 0.5])
...
TypeError: only size-1 arrays can be converted to Python scalars
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
ValueError: setting an array element with a sequence.
Yeah - but I do want do set an array element with a sequence - or at least, obtain the equivalent kind of array. How do I do that?
Upvotes: 1
Views: 361
Reputation: 2128
Use:
xm[:, :, np.newaxis]*np.array([[1.0, 1.0, 0.5]])
Output:
array([[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]]])
Upvotes: 1
Reputation: 5384
Turns out, I "simply" have to reshape the arrays - basically:
xm
of shape (4, 4) to 1D numpy array, which then has shape (16, 1);np.reshape( np.reshape(xm, (-1,1))*np.array([1,1,0.5]), (xm.shape[0], xm.shape[1], 3) )
array([[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]],
[[0. , 0. , 0. ],
[0.33333333, 0.33333333, 0.16666667],
[0.66666667, 0.66666667, 0.33333333],
[1. , 1. , 0.5 ]]])
Upvotes: 1