1
$\begingroup$

I hae a datafile with 5 columns of the structure:

x_i     f(x_i,y_1)  f(x_i,y_2) f(x_i,y_3) f(x_i,y_3) f(x_i,y_4)

with i = 1 to about 100. Thus there are about 100 lines, each corresponding to a different x-value, whereas each of the columns corresponds to a fixed y-value.

I want to interpolate on this 2D field and get f for arbitrary values (x,y). How do I bring this datafile into a form that Interpolation can work on it??

U.

$\endgroup$
2
$\begingroup$

If I understand correctly, let say you have one x column and several f[x,y] column.

For example I assume f1(x) = Sin[x],f2(x) = Cos[x] and f3(x) = Exp[x].

data = Table[{x, Sin[x], Cos[x], Exp[x]}, {x, -7, 7, .1}];
(*replace it with Import[file]*)
Do[f[i] = Interpolation[data[[All, {1, 1 + i}]]], {i, 3}]
Plot[Evaluate[Table[f[i][x], {i, 3}]], {x, -7, 7}]
(*Replace 3 by the number of unknown `f[x,y]`*)

And each f[i][x,y] corresponds the interpolating function of the individual columns

enter image description here

Example 2

Now I assume you know the x and y at which the data points are taken. Let say you choose $y=(0, \pi/2, \pi, 3\pi /2, 2 \pi)$ and each of your column contains corresponding data. Let see with a trial function Sin[x+y]

f[x_, y_] = Sin[x + y]
xval = Range[0., 2. Pi, Pi/10.];
yval = Range[0., 2. Pi, Pi/2.];
data = Table[Join[{x}, Table[f[x, y], {y, yval}]], {x, xval}];
data1 = Flatten[Table[{xval[[i]], yval[[j]], data[[i, j+1]]}, {i, Length[xval]}, {j,Length[yval]}], 1];
g = Interpolation[data1]
Plot3D[g[x, y], {x, 0, 2 Pi}, {y, 0, 2 Pi}, PlotRange -> Full]

enter image description here

g[x,y] is the function you want.

When you are importing data from a file, use

data = Import[file];
xval = data[[All,1]];
yval = {} (*write proper values*)
data1 = Flatten[Table[{xval[[i]], yval[[j]], data[[i, j+1]]}, {i, Length[xval]}, {j,Length[yval]}], 1];
g = Interpolation[data1]
Plot3D[g[x, y], {x, 0, 2 Pi}, {y, 0, 2 Pi}, PlotRange -> Full]

And you will get your interpolating function.

Corection

Thanks to george2079 for pointing out my silly mistake. It would be data[[i, j+1]] in data1. As you can see the outcome is quite close now.

$\endgroup$
  • $\begingroup$ Thank you for your help with this. I had hoped there was an easier solution! I still have a question on your example 2, which comes close to my problem: I read in the data file with the Import[file] command and then set xval and yval as you suggested. Now, what do I put in for f[x,y] in line 4 of example 2? simply replace f[x,y] by data (=Import[file])? $\endgroup$ – user3584513 Apr 24 '15 at 7:33
  • $\begingroup$ You don't need f[x,y] at all. I used it to produce the data. So you have to start from data=Import[file], define xval, yval and then go to line 5 data1=.... Follow the last structure for data file. I wrote it completely now. $\endgroup$ – Sumit Apr 24 '15 at 10:03
  • $\begingroup$ i think that should be data[[i, j+1]] $\endgroup$ – george2079 Apr 24 '15 at 12:25
  • $\begingroup$ Thanks a lot @george2079. That was the culprit causing that ugly curve. You just make my day. Let me edit my answer. $\endgroup$ – Sumit Apr 24 '15 at 12:43
1
$\begingroup$

Now that the other two answers are here, my input is somewhat redundant, but I feel, it's a good exercise in list manipulation and usage of mapping functions, so I'll leave it anyway.

Here's a solution, I feel is more readable.

First generate some fake data in your format:

f[x_, y_] := Sin[x] Exp[y]
ylist = Range@4
list = Table[{x, Sequence @@ (f[x, #] & /@ ylist)}, {x, 0, 6.28, .01}]

Now list is the data in your format and ylist is a list of y-values, which in my example is simply {1,2,3,4}. Next break the data up into a list of x-values and a table of f-values:

xlist = list[[All, 1]] (* first column of the table *)
flist = list[[All, 2 ;;]] (* second thru last columns *)

Then pass a MapIndexed on the list of f-values as follows:

MapIndexed[{{xlist[[First@#2]], ylist[[Last@#2]]}, #1} &, flist, {2}]

In MapIndexed the slot #2 stands for the position in the list, e.g {100, 3} meaning 100th row and 3rd column. We want to convert the data to a list with elements of the form {{x_i, y_i} f[x_i, y_i]} So we need to take the 100th value from xlist and the 3rd value from ylist (or other numbers, depending on the position in the table). That's exactly what the next line does.

{{xlist[[First@#2]], ylist[[Last@#2]]}, #1} &

#1 stands for the actual value of the element at position #2. Then the result needs to be flattened, so

formattedlist = Flatten[%, 1]

and it's good to be passed to Interpolation.

fun = Interpolation[formattedlist]
Plot3D[fun[x, y], {x, 0, 6.28}, {y, 1, 4}]

enter image description here

Compare to the function used to generate the fake data:

Plot3D[f[x, y], {x, 0, 6.28}, {y, 1, 4}]

enter image description here

Looks like a good match.

$\endgroup$
0
$\begingroup$

It turns out this can be done with less fuss using ListInterpolation ( data and yval as from @Sumit's answer )

 g = ListInterpolation[data[[All, 2 ;;]], {data[[All, 1]], yval}];
 Plot3D[g[x, y], {x, 0, 2 Pi}, {y, 0, 2 Pi}, PlotRange -> Full]

(* same plot *)

Better still, in this form if your y values are evenly spaced you don't even need to construct the list. Just give the range:

 ListInterpolation[data[[All, 2 ;;]], {data[[All, 1]], {0, 2 Pi}}];
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.