Hi,
I am trying to write a function that will interpolate between values in a table. I have two columns, x and y. I have a value for x, and I want to find the corresponding y based off of the data. I have a function I found that will perform a linear interpolation. However my data is not linear for the entire data set. But for small portions of the table (for example between rows 1 and 2, 2 and 3, 3 and 4... etc.) the data can be assumed to be linear.
What I want is to rewrite the linear interpolation function so that it can calculate based off of a small interval. Write now i am having trouble getting it to work, and keep getting a #Value error. I believe this is a result of the fact that my data is not sorted in terms of descending x values.
Here is the code I am using
Here is an example set of data
[TABLE="width: 180"]
<colgroup><col><col></colgroup><tbody>[TR]
[TD]1.532[/TD]
[TD]160[/TD]
[/TR]
[TR]
[TD]1.690[/TD]
[TD]133[/TD]
[/TR]
[TR]
[TD]1.630[/TD]
[TD]142[/TD]
[/TR]
[TR]
[TD]1.570[/TD]
[TD]152[/TD]
[/TR]
[TR]
[TD]1.510[/TD]
[TD]164[/TD]
[/TR]
[TR]
[TD]1.450[/TD]
[TD]177[/TD]
[/TR]
[TR]
[TD]1.390[/TD]
[TD]193[/TD]
[/TR]
[TR]
[TD]1.330[/TD]
[TD]211[/TD]
[/TR]
[TR]
[TD]1.270[/TD]
[TD]233[/TD]
[/TR]
[TR]
[TD]1.210[/TD]
[TD]259[/TD]
[/TR]
[TR]
[TD]1.150[/TD]
[TD]291[/TD]
[/TR]
[TR]
[TD]1.090[/TD]
[TD]330[/TD]
[/TR]
[TR]
[TD]1.030[/TD]
[TD]379[/TD]
[/TR]
[TR]
[TD]0.960[/TD]
[TD]453[/TD]
[/TR]
[TR]
[TD]0.900[/TD]
[TD]539[/TD]
[/TR]
[TR]
[TD]0.840[/TD]
[TD]656[/TD]
[/TR]
[TR]
[TD]0.780[/TD]
[TD]819[/TD]
[/TR]
[TR]
[TD]0.720[/TD]
[TD]1058[/TD]
[/TR]
[TR]
[TD]0.660[/TD]
[TD]1425[/TD]
[/TR]
[TR]
[TD]0.600[/TD]
[TD]2027[/TD]
[/TR]
[TR]
[TD]0.540[/TD]
[TD]3104[/TD]
[/TR]
</tbody>[/TABLE]
I am trying to write a function that will interpolate between values in a table. I have two columns, x and y. I have a value for x, and I want to find the corresponding y based off of the data. I have a function I found that will perform a linear interpolation. However my data is not linear for the entire data set. But for small portions of the table (for example between rows 1 and 2, 2 and 3, 3 and 4... etc.) the data can be assumed to be linear.
What I want is to rewrite the linear interpolation function so that it can calculate based off of a small interval. Write now i am having trouble getting it to work, and keep getting a #Value error. I believe this is a result of the fact that my data is not sorted in terms of descending x values.
Here is the code I am using
Code:
Public Function Linterp(Tbl As Range, x As Double) As Variant
' linear interpolator / extrapolator
' Tbl is a two-column range containing known x, known y, sorted x descending
Dim nRow As Long
Dim iLo As Long, iHi As Long
nRow = Tbl.Rows.Count
If nRow < 2 Or Tbl.Columns.Count <> 2 Then
Linterp = CVErr(xlErrValue)
Exit Function '-------------------------------------------------------->
End If
If x > Tbl(1, 1) Then ' x > xmax, extrapolate from first two entries
iHi = 1
iLo = 2
ElseIf x < Tbl(nRow, 1) Then ' x < xmin, extrapolate from last two entries
iHi = nRow - 1
iLo = nRow
Else
iHi = Application.Match(x, Application.Index(Tbl, 0, 1), 1)
If Tbl(iHi, 1) = x Then ' x is exact from table
Linterp = Tbl(iHi, 2)
Exit Function '---------------------------------------------------->
Else ' x is between tabulated values, interpolate
iLo = iHi + 1
End If
End If
Linterp = Tbl(iLo, 2) + (Tbl(iHi, 2) - Tbl(iLo, 2)) _
* (x - Tbl(iLo, 1)) / (Tbl(iHi, 1) - Tbl(iLo, 1))
End Function
Here is an example set of data
[TABLE="width: 180"]
<colgroup><col><col></colgroup><tbody>[TR]
[TD]1.532[/TD]
[TD]160[/TD]
[/TR]
[TR]
[TD]1.690[/TD]
[TD]133[/TD]
[/TR]
[TR]
[TD]1.630[/TD]
[TD]142[/TD]
[/TR]
[TR]
[TD]1.570[/TD]
[TD]152[/TD]
[/TR]
[TR]
[TD]1.510[/TD]
[TD]164[/TD]
[/TR]
[TR]
[TD]1.450[/TD]
[TD]177[/TD]
[/TR]
[TR]
[TD]1.390[/TD]
[TD]193[/TD]
[/TR]
[TR]
[TD]1.330[/TD]
[TD]211[/TD]
[/TR]
[TR]
[TD]1.270[/TD]
[TD]233[/TD]
[/TR]
[TR]
[TD]1.210[/TD]
[TD]259[/TD]
[/TR]
[TR]
[TD]1.150[/TD]
[TD]291[/TD]
[/TR]
[TR]
[TD]1.090[/TD]
[TD]330[/TD]
[/TR]
[TR]
[TD]1.030[/TD]
[TD]379[/TD]
[/TR]
[TR]
[TD]0.960[/TD]
[TD]453[/TD]
[/TR]
[TR]
[TD]0.900[/TD]
[TD]539[/TD]
[/TR]
[TR]
[TD]0.840[/TD]
[TD]656[/TD]
[/TR]
[TR]
[TD]0.780[/TD]
[TD]819[/TD]
[/TR]
[TR]
[TD]0.720[/TD]
[TD]1058[/TD]
[/TR]
[TR]
[TD]0.660[/TD]
[TD]1425[/TD]
[/TR]
[TR]
[TD]0.600[/TD]
[TD]2027[/TD]
[/TR]
[TR]
[TD]0.540[/TD]
[TD]3104[/TD]
[/TR]
</tbody>[/TABLE]