Question

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?

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top