I would like to implement a diagonal matrix apply function that is created by providing the diagonal d
first, and then doing a bunch of matrix-vector multiplications with x
. Of course I wouldn't want to create an actual matrix because all that's needed is a elementwise vector multiplication.
Now, some users are going to provide a diagonal d
of shape (k,)
, some of shape (k,1)
. Also, x
can have shapes (k,)
and (k,1)
. I would like the apply() method to behave just like the *
for numpy matrices in that the result has the same shape as the input x
.
Hence the question: In Python/Numpy, is there a non-iffy way to elementwise-multiply two np.arrays x
and y
of shapes (k,)
or (k,1)
(in any combination) such that the resulting array has the shape of x
?
I experimented a little with [:,None]
,
x = np.empty((4,1))
y = np.empty(4)
(x * y).shape # (4,4) -- nope
(y * y).shape # (4,) -- yes
(x * y[:,None]).shape # (4, 1) -- yes
(y * y[:,None]).shape # (4,4) -- nope
and I could certainly wrap my code in if len(x.shape)==...:
, but that doesn't feel very pythonic.
Suggestions?
multiply() function is used when we want to compute the multiplication of two array. It returns the product of arr1 and arr2, element-wise.
One dimensional array contains elements only in one dimension. In other words, the shape of the NumPy array should contain only one value in the tuple.
Now that I understand your question, my suggestion would be simply to reshape. Calling reshape
returns a view, so it doesn't incur any big copying costs or anything like that. Simply reshape the arrays, multiply, and reshape again:
>>> def shape_preserving_mult(x, y):
... return (x.reshape((-1,)) * y.reshape((-1))).reshape(x.shape)
...
Or more concisely, as you and rroowwllaanndd pointed out:
>>> def shape_preserving_mult(x, y):
... return x * y.reshape(x.shape)
...
>>> shape_preserving_mult(x, y)
array([[ 0],
[ 1],
[ 4],
[ 9],
[16]])
>>> shape_preserving_mult(x, y.T)
array([[ 0],
[ 1],
[ 4],
[ 9],
[16]])
>>> shape_preserving_mult(x.T, y)
array([[ 0, 1, 4, 9, 16]])
>>> shape_preserving_mult(x.T, y.T)
array([[ 0, 1, 4, 9, 16]])
The substance of my previous suggestion remains below.
It's worth noting that if you multiply a numpy array of shape (1, 4)
with an array of shape (4,)
you get something close to what you want.
>>> x = numpy.arange(5).reshape((5, 1))
>>> y = numpy.arange(5)
>>> x.shape
(5, 1)
>>> x.T.shape
(1, 5)
>>> y * x.T
array([[ 0, 1, 4, 9, 16]])
This doesn't have the shape of a
, but it does have the shape of a.T
. You could always call T
on the result again. This will work on arrays of shape (5,)
too, because the transpose operation on a 1-d array causes no change. So perhaps you could do this:
>>> def transposed_mult(x, y):
... return (x.T * y).T
...
>>> transposed_mult(x, y)
array([[ 0],
[ 1],
[ 4],
[ 9],
[16]])
But of course this causes the opposite problem if you pass an array of shape (1, 5)
:
>>> transposed_mult(x.T, y)
array([[ 0, 0, 0, 0, 0],
[ 0, 1, 2, 3, 4],
[ 0, 2, 4, 6, 8],
[ 0, 3, 6, 9, 12],
[ 0, 4, 8, 12, 16]])
So transposed_mult
does the exact thing you asked for in your original post, but if you need any further flexibility, it won't work as expected. And indeed, it seems you need additional flexibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With