I have a 3D surface given in data-points of the form ${x,y,z}$. What is the easiest way to get the interpolated value $z=f(X,Y)$ for given coordinates ${X,Y}$ (which are of course not in the data list)?
2 Answers
Mathematica's interpolation function, Interpolation
, works on multidimensional data. For example,
data = Flatten[Table[{x, y, x^2 + y^2}, {x, -10, 10}, {y, -10, 10}], 1];
int = Interpolation[data];
Then, you can extract the values for values between the data points:
int[1.1, 1.1]
(* ==> 2.42 *)
And Plot3D
, or whatever else you want.
Plot3D[int[x, y], {x, -10, 10}, {y, -10, 10}]
Note, that the interpolation is pretty good:
exact[x_, y_] := x^2 + y^2
int[1.1, 1.1] == exact[1.1, 1.1]
(* => True *)
Or better yet (thanks @rcollyer):
(int[1.1, 1.1] - exact[1.1, 1.1])/exact[1.1, 1.1]
(* 1.83508*10^-16 *)
Update Leonid's comment below pointed out that the accuracy of Interpolation
will be worse with an unstructured grid. For example:
dataDelete = Delete[data, RandomInteger[{1, Length[data]}]]
intD = Interpolation[dataDelete]
Then,
(intD[1.1, 1.1] - exact[1.1, 1.1])/exact[1.1, 1.1]
(* ==> 0.0743802 *)
which is worse. It seems particularly bad close to the origin:
Plot3D[(intD[x, y] - exact[x, y])/ exact[x, y], {x, -10, 10}, {y, -10, 10}]
-
$\begingroup$ What's the value of
int[1.1, 1.1] - exact[1.1, 1.1]
? That gives a better indication of fitness thenEqual
. $\endgroup$– rcollyerApr 26, 2012 at 15:58 -
5$\begingroup$ +1. Note that
Interpolation
only works on structured grids, while on unstructured ones the interpolation order will be reduced to 1, which in most cases will not be good enough. Try deleting one of the points from your regular grid to see what I mean. $\endgroup$ Apr 26, 2012 at 16:03 -
$\begingroup$ @rcollyer Good call. I've updated my answer. $\endgroup$ Apr 26, 2012 at 16:10
-
-
$\begingroup$ @LeonidShifrin Wow, it's much worse on an unstructured grid. I wonder if there's a (good) way to fill in the missing element to create a structured grid such that the interpolation is only really bad near the refilled grid point. $\endgroup$ Apr 26, 2012 at 16:23
Interpolation
. Let's create some 100x3 data matrix, coloumns representing x, y and f(x,y), covering the domain from [1,10], sampled at the integers for both x and y
data = Join[Tuples[{Range[10], Range[10]}], RandomReal[20, {100, 1}],
2];
Now, I have to apply Interpolation
to the data, but after grouping it as a list of {{x, y}, f[x,y]}
values
f = Interpolation[Through@{Most, Last}[#] & /@ data];
You can use f
as a regular function, if you keep inside the bounds of your sampling.
Let's see the results graphically
Show[ListPointPlot3D[data, PlotStyle -> PointSize[Large]],
Plot3D[f[x, y], {x, 1, 10}, {y, 1, 10}]]
-
$\begingroup$ +1 Nice visualization of the interpolation with the original data. $\endgroup$ Apr 26, 2012 at 16:10
-
2$\begingroup$ +1 for
Through@{Most,Last}
... I need to remember that for grouping! $\endgroup$– tkottApr 26, 2012 at 17:25