Interpolation Using Octave/MATLAB

Contents

Detailed Interpolation of a Single Point

The Interpolation Functions interp1

Detailed Interpolation of a Single Point

Suppose we have a rocket and have recorded it’s speed during the list of times.

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} \\ 0 & 0 \\ {10} & {227.04} \\ {15} & {362.78} \\ {20} & {517.35} \\ {22.5} & {602.97} \\ {30} & {901.67} \end{array}

And we want to know it’s speed at time t=16 s. There are a number of ways we can estimate this value or interpolate this value from the given data.

Nearest Point Interpolation (1 data point)

Simply by looking at the data we can see that the nearest time point to t=16 s is t=15 s.

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} \\ 0 & 0 \\ {10} & {227.04} \\ {15} & {362.78} \\ {20} & {517.35} \\ {22.5} & {602.97} \\ {30} & {901.67} \end{array}

We can take the speed at t=15 s and use it as a first hand estimate for the speed at t=16 s and this is known as single point interpolation.

St16=St15
St16=362.78

Linear Interpolation (2 data points)

Suppose we want to be a bit more accurate we can instead take two points and calculate the equation for a line. We can then plug in our x data point and use the equation of the straight line to estimate our unknown y data point. Looking at the data for t=16 s the nearest two time points are t=15 s and t=20 s.

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} \\ 0 & 0 \\ {10} & {227.04} \\ {15} & {362.78} \\ {20} & {517.35} \\ {22.5} & {602.97} \\ {30} & {901.67} \end{array}

The equation for a straight line is:

\displaystyle S(t)={{a}_{0}}+{{a}_{1}}t

For two times we can write this out in matrix form:

\displaystyle \left[ {\begin{array}{*{20}{c}} {S({{t}_{1}})} \\ {S({{t}_{2}})} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {{{t}_{1}}} \\ 1 & {{{t}_{2}}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \end{array}} \right]

Now we can substitute in the known values:

\displaystyle \left[ {\begin{array}{*{20}{c}} {362.78} \\ {517.35} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {15} \\ 1 & {20} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \end{array}} \right]

We can save the known data as variables S and T:

S=[362.78;517.35]

\displaystyle S=\left[ {\begin{array}{*{20}{c}} {362.78} \\ {517.35} \end{array}} \right]

T=[1,15;1,20]

\displaystyle \text{T}=\left[ {\begin{array}{*{20}{c}} 1 & {15} \\ 1 & {20} \end{array}} \right]

And call the unknown variable U:

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \end{array}} \right]

We know that:

\displaystyle \text{S}=\text{T}*\text{U}

However we want to solve for U. We can get U on it’s own by multiplying throughout by the inverse matrix of T:

\displaystyle {{\text{T}}^{{-1}}}\text{S}={{\text{T}}^{{-1}}}\text{T}*\text{U}

Since a matrix multiplied by it’s inverse gives the identity matrix and a matrix multipied by the identity matrix gets unchanged:

\displaystyle {{\text{T}}^{{-1}}}\text{S}=\text{U}

Which can be reordered:

\displaystyle \text{U=}{{\text{T}}^{{-1}}}\text{S}

Thus to solve for U we need the inverse matrix of T:

\displaystyle \text{T}=\left[ {\begin{array}{*{20}{c}} 1 & {15} \\ 1 & {20} \end{array}} \right]

This can be calculated using the function Minv=inv(M)

Tinv=inv(T)

\displaystyle \text{Tinv}=\left[ {\begin{array}{*{20}{c}} 4 & {-3} \\ {-0.2} & {0.2} \end{array}} \right]

Thus we can get the unknown coefficients of U using:

U=Tinv*S

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} 4 & {-3} \\ {-0.2} & {0.2} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {362.78} \\ {517.35} \end{array}} \right]

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {-100.93} \\ {30.914} \end{array}} \right]

i.e. in the limits of 15<t<20 a0=-100.93 and a1=30.914

Instead of using the inverse matrix we could also use left division

U=T\S

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} 1 & {15} \\ 1 & {20} \end{array}} \right]\backslash \left[ {\begin{array}{*{20}{c}} {362.78} \\ {517.35} \end{array}} \right]

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {-100.93} \\ {30.914} \end{array}} \right]

Now that we have the coefficients we can calculate the S(16)

St16=[1,16]*U

\displaystyle \text{St16}=\left[ {\begin{array}{*{20}{c}} 1 & {16} \end{array}} \right]*U=\left[ {\begin{array}{*{20}{c}} 1 & {16} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {-100.93} \\ {30.914} \end{array}} \right]

\displaystyle \text{St16}=393.69

We can check the equation using the known data:

\displaystyle \text{Stx}=\left[ {\begin{array}{*{20}{c}} 1 & {x} \end{array}} \right]*U=\left[ {\begin{array}{*{20}{c}} 1 & {x} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {-100.93} \\ {30.914} \end{array}} \right]

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} & {\begin{array}{*{20}{c}} {\text{calculated}} \\ {\text{speed (m/s)}} \end{array}} \\ 0 & 0 & {-100.93} \\ {10} & {227.04} & {208.93} \\ {15} & {362.78} & {362.78} \\ {20} & {517.35} & {517.35} \\ {22.5} & {602.97} & {594.63} \\ {30} & {901.67} & {826.49} \end{array}

Unsurprisingly the values at the limits t=15 and t=20 give exact matches. There is a slight deviation just outside this interval and a massive deviation substantially away from this interval.

Quadratic Interpolation (3 data points)

Suppose we want to be a bit more accurate we can instead take three points and calculate a quadratic equation. We can then plug in our x data point and use the quadratic equation to estimate our unknown y data point. Looking at the data for t=16 s the nearest three time points are t= 10 s, t=15 s and t=20 s.

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} \\ 0 & 0 \\ {10} & {227.04} \\ {15} & {362.78} \\ {20} & {517.35} \\ {22.5} & {602.97} \\ {30} & {901.67} \end{array}

The equation for a quadratic function is:

\displaystyle S(t)={{a}_{0}}+{{a}_{1}}t+{{a}_{2}}{{t}^{2}}

For three times we can write this out in matrix form:

\displaystyle \left[ {\begin{array}{*{20}{c}} {S({{t}_{1}})} \\ {S({{t}_{2}})} \\ {S({{t}_{3}})} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {{{t}_{1}}} & {t_{1}^{2}} \\ 1 & {{{t}_{2}}} & {t_{2}^{2}} \\ 1 & {{{t}_{3}}} & {t_{3}^{2}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \end{array}} \right]

Now we can substitute in the known values:

\displaystyle \left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} \\ 1 & {15} & {{{{15}}^{2}}} \\ 1 & {20} & {{{{20}}^{2}}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \end{array}} \right]

We can save the known data as variables S and T:

S=[227.04;362.78;517.35]

\displaystyle \text{S}=\left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \end{array}} \right]

T=[1,10,10^2;1,15,15^2;1,20,20^2]

\displaystyle \text{T}=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} \\ 1 & {15} & {{{{15}}^{2}}} \\ 1 & {20} & {{{{20}}^{2}}} \end{array}} \right]

And call the unknown variable U:

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \end{array}} \right]

To solve for U we use:

U=T\S

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} \\ 1 & {15} & {{{{15}}^{2}}} \\ 1 & {20} & {{{{20}}^{2}}} \end{array}} \right]\backslash \left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \end{array}} \right]

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {12.05} \\ {17.733} \\ {0.3766} \end{array}} \right]

i.e. in the limits of 10<t<20 a0=12.05, a1=17.733 and a2=0.3766

Now that we have the coefficients we can calculate the S(16)

St16=[1,16,16^2]*U

\displaystyle \text{St16}=\left[ {\begin{array}{*{20}{c}} 1 & {16} & {{{{16}}^{2}}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {12.05} \\ {17.733} \\ {0.3766} \end{array}} \right]

\displaystyle \text{St16}=\text{392}\text{.19}

Cubic Interpolation (4 data points)

Suppose we want to be a bit more accurate we can instead take four points and calculate a cubic equation. We can then plug in our x data point and use the cubic equation to estimate our unknown y data point. Looking at the data for t=16 s the nearest three time points are t= 10 s, t=15 s, t=20 s and t=22.5 s.

\displaystyle \begin{array}{*{20}{c}} {\text{time (s)}} & {\text{speed (m/s)}} \\ 0 & 0 \\ {10} & {227.04} \\ {15} & {362.78} \\ {20} & {517.35} \\ {22.5} & {602.97} \\ {30} & {901.67} \end{array}

The equation for a cubic function is:

\displaystyle S(t)={{a}_{0}}+{{a}_{1}}t+{{a}_{2}}{{t}^{2}}+{{a}_{3}}{{t}^{3}}

For four times we can write this out in matrix form:

\displaystyle \left[ {\begin{array}{*{20}{c}} {S({{t}_{1}})} \\ {S({{t}_{2}})} \\ {S({{t}_{3}})} \\ {S({{t}_{4}})} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {{{t}_{1}}} & {t_{1}^{2}} & {t_{1}^{3}} \\ 1 & {{{t}_{2}}} & {t_{2}^{2}} & {t_{2}^{3}} \\ 1 & {{{t}_{3}}} & {t_{3}^{2}} & {t_{3}^{2}} \\ 1 & {{{t}_{4}}} & {t_{4}^{2}} & {t_{4}^{2}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \\ {{{a}_{3}}} \end{array}} \right]

Now we can substitute in the known values:

\displaystyle \left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \\ {602.97} \end{array}} \right]=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} & {{{{10}}^{3}}} \\ 1 & {15} & {{{{15}}^{2}}} & {{{{15}}^{3}}} \\ 1 & {20} & {{{{20}}^{2}}} & {{{{20}}^{3}}} \\ 1 & {22.5} & {{{{22.5}}^{2}}} & {{{{22.5}}^{3}}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \\ {{{a}_{3}}} \end{array}} \right]

We can save the known data as variables S and T:

S=[227.04;362.78;517.35;602.97]

\displaystyle \text{S}=\left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \\ {602.97} \end{array}} \right]

T=[1,10,10^2,10^3;1,15,15^2,15^3;1,20,20^2,20^3;1,22.5,22.5^2,22.5^3]

\displaystyle \text{T}=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} & {{{{10}}^{3}}} \\ 1 & {15} & {{{{15}}^{2}}} & {{{{15}}^{3}}} \\ 1 & {20} & {{{{20}}^{2}}} & {{{{20}}^{3}}} \\ 1 & {22.5} & {{{{22.5}}^{2}}} & {{{{22.5}}^{3}}} \end{array}} \right]

And call the unknown variable U:

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {{{a}_{0}}} \\ {{{a}_{1}}} \\ {{{a}_{2}}} \\ {{{a}_{3}}} \end{array}} \right]

To solve for U we use:

U=T\S

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} 1 & {10} & {{{{10}}^{2}}} & {{{{10}}^{3}}} \\ 1 & {15} & {{{{15}}^{2}}} & {{{{15}}^{3}}} \\ 1 & {20} & {{{{20}}^{2}}} & {{{{20}}^{3}}} \\ 1 & {22.5} & {{{{22.5}}^{2}}} & {{{{22.5}}^{3}}} \end{array}} \right]\backslash \left[ {\begin{array}{*{20}{c}} {227.04} \\ {362.78} \\ {515.35} \\ {602.97} \end{array}} \right]

\displaystyle \text{U}=\left[ {\begin{array}{*{20}{c}} {-4.254} \\ {21.2655333} \\ {0.13204} \\ {0.0054347} \end{array}} \right]

i.e. in the limits of 10<t<22.5 a0=4.254, a1=21.2655333, a2=0.13204 and a3=0.0054347

Now that we have the coefficients we can calculate the S(16)

St16=[1,16,16^2,16^3]*U

\displaystyle \text{St16}=\left[ {\begin{array}{*{20}{c}} 1 & {16} & {{{{16}}^{2}}} & {{{{16}}^{3}}} \end{array}} \right]*\left[ {\begin{array}{*{20}{c}} {-4.254} \\ {21.2655333} \\ {0.13204} \\ {0.0054347} \end{array}} \right]

\displaystyle \text{St16}=392.06

Comparison

We can compare our interpolation for t=16 using the four different methods. As we can see when we are interpolating with higher order polynomials the result begins to converge as expected:

\displaystyle \begin{array}{*{20}{c}} {\text{method}} & {\begin{array}{*{20}{c}} {\text{no of data}} \\ {\text{points}} \end{array}} & {\text{St16}} \\ {\text{nearest}} & 1 & {362.78} \\ {\text{linear}} & 2 & {393.69} \\ {\text{quadratic}} & 3 & {392.19} \\ {\text{cubic}} & 4 & {392.06} \end{array}

Interpolation of a Data Set

As we seen it is quite involved interpolating the data for a single data point. If we want to interpolate 100’s or even 1000’s of data points manually going through them all like above it would take all day. Luckily Octave/MATLAB have inbuilt interpolation functions.

intery=interp1(originalx,originaly,xdatapoints,'Method')

We can type in the data using Octave/MATLAB.


data=[0,0;
10,227.04;
15,362.78;
20,517.35;
22.5,602.97;
30,901.67]

We could also use Excel to copy and paste in the data. In MATLAB which is more polished, we can directly go to the variable editor, right click it and create a new variable and then name accordingly. This option isn’t available in Octave however we can quickly create a variable, assign in to a scalar and then copy and paste in a matrix in the variable editor.

For instance typing in:

data=1;

Then clicking the new variable data in the workspace to open it up in the variable editor:

We can right click the top cell of data in the variable editor and we can right click Paste Table to copy the Excel Data through to Octave:

Now we have our data variable:

Next we need to make the new x data. For this I am going to make a new variable called dataint and I want the first column to go from 1 to 30. Here logical indexing is used when creating the variable dataint. The (:,1) means we are creating data in all rows but using the first column. The [1:30]' is a column vector ranging from 1 to 30 in steps of 1. If you are unsure about logical indexing see my earlier guide Introduction to Arrays.

dataint(:,1)=[1:30]'

Now we are looking to interpolate the data:

intery=interp1(originalx,originaly,xdatapoints,'Method')

Our original x data originalx is the first column of data our original y data originaly is the second column of data

originalx=data(:,1)

originaly=data(:,2)

Our x datapoints xdatapoints are the first column in dataint

xdatapoints=dataint(:,1)

We will start with Nearest Interpolation meaning instead of typing in 'Method' we type in 'Nearest'. We can now get intery:

intery=interp1(originalx,originaly,xdatapoints,'Nearest')

We can clear up our code here:

intery=interp1(originalx,originaly,xdatapoints,'Nearest')

By substituting these in directly:

originalx=data(:,2)

originaly=data(:,2)

xdatapoints=dataint(:,1)

This becomes

intery=interp1(data(:,1),data(:,2),dataint(:,1),'Nearest')

Now it is more likely we want the y data to be alongside the xdatapoints so instead of having the separate output variable intery we can add it as a second column to dataint by using:

dataint(:,2)=interp1(data(:,1),data(:,2),dataint(:,1),'Nearest')

We can press the [↑] key to get our last line of code and easily modify the line of code to print linear interpolated data to column 3. For linear interpolation the method is 'Linear':

dataint(:,3)=interp1(data(:,1),data(:,2),dataint(:,1),'Linear')

MATLAB/Octave’s interp1 function doesn’t have an inbuilt quadratic interpolation so I will go directly to cubic interpolation and here the method is 'Pchip' , this time I want the data in the 4th column.

dataint(:,4)=interp1(data(:,1),data(:,2),dataint(:,1),'Pchip')

Since we were interested at the value at t=16 which is the 16th row we can output the 16th row into the command window:

t16row=dataint(16,:)

These are very similar to the values manually calculated, the differences are likely due to rounding.

The code above can be cleared up and put in a script file.

% Data
data=[0,0;
10,227.04;
15,362.78;
20,517.35;
22.5,602.97;
30,901.67];

% Lower and Upper Limits for interpolation
m=1;
n=30;

% Interpolation Spreadsheet
dataint(:,1)=[m:n]';
dataint(:,2)=interp1(data(:,1),data(:,2),dataint(:,1),'Nearest');
dataint(:,3)=interp1(data(:,1),data(:,2),dataint(:,1),'Linear');
dataint(:,4)=interp1(data(:,1),data(:,2),dataint(:,1),'Pchip');