2010-07-14 39 views
4

這份名單插值是一個簡單的函數,一個2D點映射到一個號碼,如果 把每個{{x,y},z}f[x,y]=z力數學對非結構化張格

{ 
{{1,3},9}, {{1,4},16}, 
{{2,4},8}, {{2,5},10} 
} 

我現在想要一個函數,插值/外推​​任何{x,y}

數學拒絕這樣做:

Interpolation[{{{1,3},9}, {{1,4},16},{{2,4},8}, {{2,5},10}}, 
InterpolationOrder->1] 

插值:: indim:本 座標不處在一個結構性 張量積網格。

我明白爲什麼(數學想要一個「矩形」域),但 什麼是強迫數學創建插值最簡單的方法?

這不起作用:

f[1,3]=9; f[1,4]=16; f[2,4]=8; f[2,5]=10; 
g=FunctionInterpolation[f[x,y],{x,1,2},{y,3,5}] 

FunctionInterpolation :: nreal:
16附近{X,Y} = {1, - },這個函數不 計算爲一個真正的數。 5 FunctionInterpolation :: nreal:
17在{x,y} = {1, - }附近,函數沒有將 評估爲實數。 5 FunctionInterpolation :: nreal:
18在{x,y} = {1, - }附近,函數沒有將 評估爲實數。 5 General :: stop:進一步輸出 FunctionInterpolation :: nreal 將在此計算過程中被抑制。

即使你忽略上面的警告,評估摹給出錯誤

g[1.5,4] // FortranForm 


    f(1.5,4) + 0.*(-9.999999999999991*(f(1.4,4) - f(1.5,4)) + 
-  0.10000000000000009* 
-  (9.999999999999991* 
-   (9.999999999999991*(f(1.4,4) - f(1.5,4)) + 
-   4.999999999999996*(-f(1.4,4) + f(1.6,4))) + 
-   0.5000000000000006* 
-   (-10.000000000000014* 
-    (-3.333333333333333*(f(1.3,4) - f(1.6,4)) - 
-    4.999999999999996*(-f(1.4,4) + f(1.6,4))) - 
-   9.999999999999991* 
-    (9.999999999999991*(f(1.4,4) - f(1.5,4)) + 
-    4.999999999999996*(-f(1.4,4) + f(1.6,4)))))) 

其他「明顯」的想法(內插值功能 本身)也不起作用。

回答

6

如果多項式插值是可以接受的,InterpolatingPolynomial你想要做什麼(其中data是您點的列表上方):

In[63]:= InterpolatingPolynomial[data, {x, y}] 

Out[63]= -24 + x (12 - 5 y) + 12 y 

In[64]:= f[2, 3] 

Out[64]= 6 

你也可以使用Fit做最小二乘上的函數的線性組合擬合在第二個參數中指定:

In[65]:= Fit[Flatten /@ data, {1, x, y}, {x, y}] 

Out[65]= 4.75 - 8. x + 4.5 y 

當然,擬合的函數可能不會精確地插入您的數據點。如果這樣的配件是可以接受的,雖然,FindFit可以適合任何(線性或非線性)模型函數指定:

In[72]:= FindFit[Flatten/@data, x y (a Sin[x] + b Cos[y]) + c, {a,b,c}, {x,y}] 

Out[72]= {a -> -0.683697, b -> 0.414257, c -> 15.3805} 

HTH!

1

不幸的是,多項式太誇張了,但是線性函數並不是 就足夠了。我相信正確的模型是幾個線段, ,但他們都會有不同的斜坡。

這是一個可怕的解決方法,可以做我想做的事情。


(* data in format {{x,y},z} *) 
data = {{{1,3},9}, {{1,4},16}, {{2,4},8}, {{2,5},10}} 

(* find the ranges of x and y *) 
datax = DeleteDuplicates[Transpose[Transpose[data][[1]]][[1]]] 
datay = DeleteDuplicates[Transpose[Transpose[data][[1]]][[2]]] 

(* extract the values of y and z for each x *) 
datamap[t_]:=Map[{#[[1,2]], #[[2]]} &, Select[data, #[[1,1]] == t &]] 

(* interpolate for each value of x, create a rectangular array, and then 
    interpolate in y *) 
Map[(f[#]=Interpolation[datamap[#],InterpolationOrder->1])&, datax] 

(* and now apply f to the expanded grid I've created *) 

datatab = Flatten[Table[ 
{{datax[[i]], datay[[j]]}, f[datax[[i]]][datay[[j]]]}, 
{i,1,Length[datax]}, {j,1,Length[datay]}], 1] 

(* now mathematica will let me interpolate *) 
dataint = Interpolation[datatab, InterpolationOrder->1] 

(* The resulting function agrees with my original*) 

Flatten[Table[{{x,y},dataint[x,y]},{x,1,2},{y,3,5}],1] 

Out[29]= {{{1, 3}, 9}, {{1, 4}, 16}, {{1, 5}, 23}, {{2, 3}, 6}, {{2, 4}, 8}, 
{{2, 5}, 10}} 

(* above contains all my original points [plus a few extra] *) 

(* and does a reasonable job of interpolating *) 

dataint[1.5,3.5] 

9.75 

which is the average of the four corner values: 

{dataint[1,3], dataint[1,4], dataint[2,3], dataint[2,4]} 

{9, 16, 6, 8}