Reputation: 13
I'm trying to write a function in Python using Numpy that would take as input a vector x = array([x_1, x_2, ..., x_n])
and a positive integer m
and return an array of dimension n
by m
of the form (say n==3
, m==4
):
array([[ x_1, x_1^2, x_1^3, x_1^4],
[ x_2, x_2^2, x_2^3, x_2^4],
[ x_3, x_3^2, x_3^3, x_3^4]])
So far I have
import numpy as np
def f(x, m):
return x ** np.arange(1, m+1)
which works fine for n==1
, but raises an exception for n > 1
.
I am trying to avoid using loops. Is there a nice way of making this in Numpy?
Thank you!
Upvotes: 1
Views: 199
Reputation: 53079
You can
np.vander
x = np.array([2.3,1.3,4.4])
m = 4
np.vander(x,m+1,True)[:,1:]
# array([[ 2.3 , 5.29 , 12.167 , 27.9841],
# [ 1.3 , 1.69 , 2.197 , 2.8561],
# [ 4.4 , 19.36 , 85.184 , 374.8096]])
or
np.power.outer
np.power.outer(x,np.arange(1,m+1))
# same output
or
np.logspace
np.logspace(1,m,m,True,x[:,None])
# same output
or
np.multply.accumulate
or cumprod
np.multiply.accumulate(np.broadcast_to(x,(m,np.size(x))),axis=0).T
# same output
np.broadcast_to(x,(m,np.size(x))).cumprod(axis=0).T
# same output
Upvotes: 1
Reputation: 1048
You can use broadcasting for this:
def f(x, m):
return x[:, np.newaxis] ** np.arange(1, m + 1)[np.newaxis, :]
This sets x as a shape (n, 1) vector, the range as a (1, m) vector, and has them interact in the way that you want.
Here's what it looks like in my IPython REPL.
In [1]: import numpy as np
In [2]: def f(x, m):
...: return x[:, np.newaxis] ** np.arange(1, m + 1)[np.newaxis, :]
...:
In [3]: x = np.array([1,2,3,4,5])
In [4]: f(x, 6)
Out[4]:
array([[ 1, 1, 1, 1, 1, 1],
[ 2, 4, 8, 16, 32, 64],
[ 3, 9, 27, 81, 243, 729],
[ 4, 16, 64, 256, 1024, 4096],
[ 5, 25, 125, 625, 3125, 15625]])
Upvotes: 1