SciPy interp2D for coordinate pairs

I use scipy.interpolate.interp2d to create an interpolation function for the surface. Then I have two arrays of real data for which I want to calculate the interpolated points. If I pass two arrays to interp2d , I get an array of all points, not just a pair of points.

My solution is to pin two arrays to a list of coordinate pairs and pass this to the interpolation function in a loop:

 f_interp = interpolate.interp2d(X_table, Y_table,Z_table, kind='cubic') co_ords = zip(X,Y) out = [] for i in range(len(co_ords)): X = co_ords[i][0] Y = co_ords[i][1] value = f_interp(X,Y) out.append(float(value)) 

My question is, is there a better (more elegant, Pythonic?) Way to achieve the same result?

+5
source share
4 answers

First you can do

 for Xtmp,Ytmp in zip(X,Y): ... 

in your cycle. Or even better, just

 out = [float(f_interp(XX,YY)) for XX,YY in zip(X,Y)] 

replacing the loop.

In another note , I suggest using interpolate.griddata instead . It tends to behave much better than interp2d , and it accepts arbitrary points as input. As you saw, interp2d interpolators will only return values โ€‹โ€‹in a cell.

+1
source

Passing all your points at once will probably be much faster than switching to them in Python. You can use scipy.interpolate.griddata :

 Z = interpolate.griddata((X_table, Y_table), Z_table, (X, Y), method='cubic') 

or one of the scipy.interpolate.BivariateSpline classes, for example. SmoothBivariateSpline :

 itp = interpolate.SmoothBivariateSpline(X_table, Y_table, Z_table) # NB: choose grid=False to get an (n,) rather than an (n, n) output Z = itp(X, Y, grid=False) 

CloughTocher2DInterpolator also works in a similar way, but without the grid=False parameter (it always returns the 1st output).

+3
source

Try * args and a packing / unpacking tuple

 points = zip(X, Y) out = [] for p in points: value = f_interp(*p) out.append(float(value)) 

or simply

 points = zip(X, Y) out = [float(f_interp(*p)) for p in points] 

or simply

 out = [float(f_interp(*p)) for p in zip(X, Y)] 

as a side note, the โ€œmagic starโ€ allows zip to be its own reverse!

 points = zip(x, y) x, y = zip(*points) 
+2
source

Inspired by this thread, where someone recommends using the internal weights of the interp2d function, I created the following wrapper that has exactly the same interface as interp2d but the interpolant evaluates the input pairs and returns an array of empty arrays of the same form of its input., Performance should be better than for loops or comprehension of lists, but when evaluating on a grid, it will outperform scipy interp2d .

 import scipy.interpolate as si def interp2d_pairs(*args,**kwargs): """ Same interface as interp2d but the returned interpolant will evaluate its inputs as pairs of values. """ # Internal function, that evaluates pairs of values, output has the same shape as input def interpolant(x,y,f): x,y = np.asarray(x), np.asarray(y) return (si.dfitpack.bispeu(f.tck[0], f.tck[1], f.tck[2], f.tck[3], f.tck[4], x.ravel(), y.ravel())[0]).reshape(x.shape) # Wrapping the scipy interp2 function to call out interpolant instead return lambda x,y: interpolant(x,y,si.interp2d(*args,**kwargs)) # Create the interpolant (same interface as interp2d) f = interp2d_pairs(X,Y,Z,kind='cubic') # Evaluate the interpolant on each pairs of x and y values z=f(x,y) 
0
source

Source: https://habr.com/ru/post/1242856/


All Articles