I have a dataset (X,Y) -> Z. Therefore, I would like to learn in Python the mapping between the 2D input and the output Z.
I know that the underlying function is not linear, thus I cannot apply linear regression. Since the input data is only 2D, I would like to use the bivariate spline. I implemented the following example:
import numpy
from scipy import interpolate
X = [1,2,1,2]
Y = [1,2,2,1]
Z = [1,2,1,2]
Y = numpy.array(Y)
X = numpy.array(X)
Z = numpy.array(Z)
tck = interpolate.bisplrep(X,Y,Z)#,kx=5,ky=2)
print interpolate.bisplev(1.5,1.5,tck)
However, the code above raises the following error:
File "/usr/lib/python2.7/dist-packages/scipy/interpolate/fitpack.py", line 850, in bisplrep
TypeError: m >= (kx+1)(ky+1) must hold
The problem is that the scipy implementation of bivariate spline requires grid data as input rather than a normal array of the input sequence, such as X = [x1, x2,...] and Y = [y1,y2,...]. Due to the type of data available to me, I cannot build a grid because the input data is not regularly distibuted.
How can I do a bivariate spline with input data that is not a grid?
If it is not possible, is there another way to do 2D spline / polynomial fitting / non-linear regression in Python?
TypeError: m >= (kx+1)(ky+1) must hold
means that you've supplied too few points, not that the data must be grid data. m is equal to len(X) (or len(Y), or len(Z)).
kx and ky control the degree of the spline.
So, for example, if you increase the length of x, y and z:
import scipy.interpolate as interpolate
x = [1,2,1,2,1,3,2,3,3]
y = [1,2,2,1,3,1,3,2,3]
z = [1,2,1,2,0,0,0,0,0]
kx, ky = 2, 2 # spline order
assert len(x) >= (kx+1)*(ky+1)
tck = interpolate.bisplrep(x, y, z, kx=kx, ky=ky)
print(interpolate.bisplev(1.5,1.5,tck))
prints
2.109375
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