I need a function to lookup several values from an array, depending on another value (in this case, time). This can also be thought of as "previous value interpolation". This just works in Matlab/Octave:
inputArray = [3600, 60, 50, 40; 3700, 0, 50, 40; 7260, 200, 20, 10];
t_current = 3650;
inputVector = interp1(inputArray(:,1), inputArray(:, 2:end), t_current, 'previous', 0)
and gives
inputVector =
60 50 40
as expected. How can this be done in Python?
The following works, but is rather clumsy, since I need to repeat the interp1d
command for every column of inputArray
!
import numpy as np
from scipy.interpolate import interp1d
# Time, q_in, x_in, y_in
inputArray = np.array(([3600, 60, 50, 40], [3700, 0, 50, 40], [7260, 200, 20, 10]))
t_current = 3650
itp_q_in = interp1d(inputArray[:,0], inputArray[:,1], kind='previous', \
bounds_error=False, fill_value=(0, 0)) # Works
# Repeat for each column(!!!)
itp_x_in = interp1d(inputArray[:,0], inputArray[:,2], kind='previous', \
bounds_error=False, fill_value=(0, 0))
itp_y_in = interp1d(inputArray[:,0], inputArray[:,3], kind='previous', \
bounds_error=False, fill_value=(0, 0))
# Throws ValueError: x and y arrays must be equal in length along interpolation axis.
#itp_qxy_in = interp1d(inputArray[:,0], inputArray[:,1:], kind='previous', \
# bounds_error=False, fill_value=(0, 0))
inputVector = np.array([itp_q_in(t_current), itp_x_in(t_current), itp_y_in(t_current)])
and gives
inputVector
array([60., 50., 40.])
Is there not a more compact version to write this? My real inputArray
might easily have up to 50 columns!!!
CodePudding user response:
The scipy function supports the exact same functionality as that of Matlab's, with the exact same syntax. From the docs:
y: (…,N,…) array_like
A N-D array of real values. The length of y along the interpolation axis must be equal to the length of x.
And in code (note the axis=0
argument):
>>> interp1d(inputArray[:,0], inputArray[:,1:], kind='previous', axis=0)(t_current)
array([60., 50., 40.])
The error your itp_qxy_in
throws is quite explicit. The reason why it happens is because the axis
argument defaults to -1 and will thus interpolate along the columns. This is of course in your actual code where you may have 50 columns. In your toy example here inputArray[:,1:]
happens to be a 3x3 array and it will happily integrate along either axis (of course axis=-1 will still give the wrong result).
Edit:
Matlab and numpy have different array layouts. The former is column major and the latter row major. It would be better to have your data transposed to the way you actually type them in Matlab. And then the axis=-1
argument becomes more natural.
a = inputArray.T
interp1d(a[0], a[1:], kind='previous')(t_current)