Converting bsxfun with @times to numpy
bsxfun
in Matlab stand for binary singleton expansion, in numpy it's called broadcasting and should happen automatically. The solution will depend on the dimensions of your X
, i.e. is it a row or column vector but this answer shows one way to do it:
How to multiply numpy 2D array with numpy 1D array?
I think that the issue here is that broadcasting requires one of the dimensions to be 1
and, unlike Matlab, numpy seems to differentiate between a 1 dimensional 2 element vector and a 2 dimensional 2 element, i.e. the difference between a matrix of shape (2,)
and of shape (2,1)
, you need the latter for broadcasting to happen.
For those who don't know Numpy, I think it's worth pointing out that the equivalent of Octave's (and Matlab's) *
operator (matrix multiplication) is numpy.dot
(and, debatably, numpy.outer
). Numpy's *
operator is similar to bsxfun(@times,...)
in Octave, which is itself a generalization of .*
.
In Octave, when applying bsxfun, there are implicit singleton dimensions to the right of the "true" size of the operands; that is, an n1 x n2 x n3
array can be considered as n1 x n2 x n3 x 1 x 1 x 1 x...
. In Numpy, the implicit singleton dimensions are to the left; so an m1 x m2 x m3
can be considered as ... x 1 x 1 x m1 x m2 x m3
. This matters when considering operand sizes: in Octave, bsxfun(@times,a,b)
will work if a is 2 x 3 x 4
and b is 2 x 3
. In Numpy one could not multiply two such arrays, but one could multiply a 2 x 3 x 4
and a 3 x 4
array.
Finally, bsxfun(@times, X*Y, X)
in Octave will probably look something like numpy.dot(X,Y) * X
. There are still some gotchas: for instance, if you're expecting an outer product (that is, in Octave X is a column vector, Y a row vector), you could look at using numpy.outer
instead, or be careful about the shape of X and Y.
Little late, but I would like to provide an example of having equivalent bsxfun
and repmat
in python. This is a little bit of code I was just converting from Matlab to Python numpy:
Matlab:
x = -2 -1 0 1 2n = 2M = repmat(x,1,n+1)M = -2 -2 -2 -1 -1 -1 0 0 0 1 1 1 2 2 2M = bsxfun(@power,M,0:n)M = 1 -2 4 1 -1 1 1 0 0 1 1 1 1 2 4
Equivalent in Python:
In [8]: xOut[8]: array([[-2], [-1], [ 0], [ 1], [ 2]])In [9]: n=2In [11]: M = np.tile(x, (1, n + 1))In [12]: MOut[12]: array([[-2, -2, -2], [-1, -1, -1], [ 0, 0, 0], [ 1, 1, 1], [ 2, 2, 2]])In [13]: M = np.apply_along_axis(pow, 1, M, range(n + 1))In [14]: MOut[14]: array([[ 1, -2, 4], [ 1, -1, 1], [ 1, 0, 0], [ 1, 1, 1], [ 1, 2, 4]])