I have two 2D array, x(ni, nj) and y(ni,nj), that I need to interpolate over one axis. I want to interpolate along last axis for every ni.
I wrote
import numpy as np
from scipy.interpolate import interp1d
z = np.asarray([200,300,400,500,600])
out = []
for i in range(ni):
f = interp1d(x[i,:], y[i,:], kind='linear')
out.append(f(z))
out = np.asarray(out)
However, I think this method is inefficient and slow due to loop if array size is too large. What is the fastest way to interpolate multi-dimensional array like this? Is there any way to perform linear and cubic interpolation without loop? Thanks.
The method you propose does have a python loop, so for large values of
niit is going to get slow. That said, unless you are going to have largeniyou shouldn’t worry much.I have created sample input data with the following code:
And have tested them with this two versions of linear interpolation:
interp_1is an optimized version of your code, following Dave’s answer.interp_2is a vectorized implementation of linear interpolation that avoids any python loop whatsoever. Coding something like this requires a sound understanding of broadcasting and indexing in numpy, and some things are going to be less optimized than whatinterp1ddoes. A prime example being finding the bin in which to interpolate a value:interp1dwill surely break out of loops early once it finds the bin, the above function is comparing the value to all bins.So the result is going to be very dependent on what
n_iandn_jare, and even how long your arrayzof values to interpolate is. Ifn_jis small andn_iis large, you should expect an advantage frominterp_2, and frominterp_1if it is the other way around. Smallerzshould be an advantage tointerp_2, longer ones tointerp_1.I have actually timed both approaches with a variety of
n_iandn_j, forzof shape(5,)and(50,), here are the graphs:So it seems that for
zof shape(5,)you should go withinterp_2whenevern_j < 1000, and withinterp_1elsewhere. Not surprisingly, the threshold is different forzof shape(50,), now being aroundn_j < 100. It seems tempting to conclude that you should stick with your code ifn_j * len(z) > 5000, but change it to something likeinterp_2above if not, but there is a great deal of extrapolating in that statement! If you want to further experiment yourself, here’s the code I used to produce the graphs.