Introduction to Fitting Data

Math 245 - Mathematical Models
February 22, 2010

Applying transformations to data

Applying a transformation to a list

Most Mathematical transformations can be performed directly on a list without having to modify the individual entries.  For example, given the list xdata below, it is easy to square the entries, find the reciprocal of the entries, take the natural log of the entries, or apply a more intricate transformation directly to the list.

xdata={1,2,3,4,5};
xdata^2
1/xdata
Log[xdata]
Sin[Pi xdata/2]^3+5

As you recall from class, it is often necessary to do such a transformation of the x- and/or y-coordinate data in order to transform a non-linear relationship into a linear relationship.  Here are two examples:

Example 1. Data of the form y = ((Cx)^k)

Remember that with data of the form y = ((Cx)^k), you must take the log of both sides to get Log[y] = Log[C]+kLog[x]; you must then plot Log[y] as a function of Log[x] to find the slope (k) and the y-intercept (Log[C]).

First here is the graph of the original data; notice that we have a list of the x-coordinates and a list of the y-coordinates and we use a Table command to assemble these into datapoints.

xdata={1,2,3,4,5,6};
ydata={0.5,3,9,21,42,72};
points2=Table[{xdata[[i]],ydata[[i]]},{i,1,Length[xdata]}]
ListPlot[points2,PlotStyle->{PointSize[Medium]},AxesOrigin->{0,0}]

Now we take the natural log of both lists of coordinates and assemble these transformed coordinates into datapoints, which, in turn, are plotted.

Logx=Log[xdata];
Logy=Log[ydata];
points2=Table[{Logx[[i]],Logy[[i]]},{i,1,Length[xdata]}]
ListPlot[points2,PlotStyle->{PointSize[Medium]},AxesOrigin->{-.2,-1}]

Example 2. Data of the form y = ((Ck)^x)

Remember that with data of the form y = ((Ck)^x), you must take the log of both sides to get Log[y] = Log[C]+xLog[k]; you must then plot Log[y] as a function of x to find the slope (Log[k]) and the y-intercept (Log[C]).

xdata={1,2,3,4,5,6};
ydata={1,2,7,20,61,182};
points2=Table[{xdata[[i]],ydata[[i]]},{i,1,Length[xdata]}]
ListPlot[points2,PlotStyle->{PointSize[Medium]},AxesOrigin->{0,0}]

Logy=Log[ydata];
points2=Table[{xdata[[i]],Logy[[i]]},{i,1,Length[xdata]}]
ListPlot[points2,PlotStyle->{PointSize[Medium]},AxesOrigin->{-.2,-1}]

Using Mathematica to do a Least-Squares Fit

Introduction to Fit

When you want Mathematica to do function fitting, use either the function Fit or FindFit.  You will use Fit when you are trying to determine constants that are linear combinations of input data, such as y=a*x^2+b*x+c or z=a*x^2+b*x*y+c*y^2.  (Notice how the constants a, b, and c are simply multiplying the variables involved with the data.)  When the relationship between the constants and the data is not as simple, use the function FindFit. As an example, you can determine the constants a, b, c, and d in curves of the form a*x*Log[b+c*x] or a+b*Sin[c*x+d].

Let's analyze the structure of a Fit command that finds the constants of a linear regression (y=ax+b).  
Notice that I give the function determined by the fit a name for use later.

data={{0,1},{1,0},{3,2},{5,4}};
line=Fit[data, {x,1},x]

There are always three inputs: the data, the functions the unknown constants are multiplied by, and the variables.
The data is a list of data points that looks like {x_i,y_i} (when y is supposed to be a function of x), or {x_i,y_i,z_i} (when z is a function of x and y).  Data points involving more variables are also allowed; the independent variables always come first and the dependent variable is at the end.
The last input is the list of variables involved; this lets you name the independent variables to your liking.  For example, when the data points are {x,y}, the last input would be x; if the data points are {x,y,z}, the last input would be {x,y}.  
The middle input is the set of functions of which the dependent variable is supposed to be a linear function.  For example, when you hope to fit a curve of the form such as y=a*x^2+b*x+c, then the middle input would be {x^2,x,1}; in the case of z=a*x^2+b*x*y+c*y^2, the middle input would be {x^2,x*y,y^2}.  These functions can be as involved as you like.

Continuation of Example 1.

In our first example from above, we want to determine the constants Log[c] and k in Log[y]=Log[C]+kLog[x].  The way to do this in Mathematica is:

(* First define all the required datapoints *)
xdata={1,2,3,4,5,6};
ydata={0.5,3,9,21,42,72};
points1=Table[{xdata[[i]],ydata[[i]]},{i,1,Length[xdata]}];
Logx=Log[xdata];
Logy=Log[ydata];
points2=Table[{Logx[[i]],Logy[[i]]},{i,1,Length[xdata]}];

(* This line of code does the linear fit *)
line=Fit[points2,{1,x},x]

(* Now plot the data and the linear fit; remember you need to use the Show command. *)
plot1=ListPlot[points2,PlotStyle->{PointSize[Medium]},AxesOrigin->{-.2,-1}];
plot2=Plot[line,{x,0,2}];
Show[plot1,plot2]

Read off the value of line to see that k (the slope of the line) is approximately 2.7756 and that ln[C] (the y-intercept) is approximately -0.7666; to solve for C, exponentiate:

Exp[-0.7666706104156896]

That means that the original data should fit the curve y=(0.464557)x^(2.77563), which we can verify by plotting it against the original data:

curve=(0.464557)x^(2.77563);
plot1=ListPlot[points1,PlotStyle->{PointSize[Medium]},AxesOrigin->{-.2,-1}];
plot2=Plot[curve,{x,0,7}];
Show[plot1,plot2]

Introduction to FindFit

Now let's analyze the structure of a FindFit command that finds the constants of a fit of (z=cy+x^k).

data={{0.1,1,10},{1,0,23},{3,2,50},{5,4,100}};
FindFit[data,c*y+x^k, {c,k},{x,y}]

There are now four inputs: the data (just as in Fit), the function that we wish to fit, the constants to be found, and the variables (just as in Fit).
The second input is the function involving the independent variables and the constants that need to be found; this is a more input than in Fit.  For example, you can insert functions of the type  a+b*Sin[c*x+d] or a*y*Log[b+c*x], each of which mixes the independent variables (x, y) from the data and constants (a,b,c).  Of course, now that the equation involves both constants and independent variables, we must tell Mathematica which are which.  The constants are the third input and the independent variables are the fourth input.

Alternate Continuation of Example 1.

In our first example from above, we want to determine the constants Log[c] and k in Log[y]=Log[C]+kLog[x].  The way to do this in Mathematica is:

(* First define all the required datapoints *)
xdata={1,2,3,4,5,6};
ydata={0.5,3,9,21,42,72};
points1=Table[{xdata[[i]],ydata[[i]]},{i,1,Length[xdata]}];

(* This line of code does the linear fit *)
FindFit[points1,c*x^k, {c,k},{x}]

That means that the data should fit the curve y=(0.334263)x^(2.99898), which we can verify by plotting it against the original data:

curve=(0.334263)x^(2.99898);
plot1=ListPlot[points1,PlotStyle->{PointSize[Medium]},AxesOrigin->{-.2,-1}];
plot2=Plot[curve,{x,0,7}];
Show[plot1,plot2]

Comprehension Questions

Use the method of transforming data and doing a linear fit to determine approximate values for the constants C and k for the data given in Example 2.

Determine the constants C and k for the data in Example 2 directly using the FindFit command.

Which method seems to give a better fit to the original data?  Which method do you prefer, and why?

The list data2 in the code below is the NYC temperature data we analyzed in class.  Fit this data to the function a+b*Sin[c x+d].  Compare the result to the answer given in class when we assumed values for C and D.

<<"Units`";
data=WeatherData["KLGA", "MeanTemperature", {{2006, 1, 1}, {2008, 12, 31}, "Week"},"DateValue"];
data2=Table[{(DateDifference[{2006,1,1},data[[i,1]]]/365) ,ConvertTemperature[data[[i,2]],Celsius,Fahrenheit]},{i,Length[data]}];