5
$\begingroup$

Say I have these data:

data = {{1, 3}, {2, 4}, {3, 6}, {4, 7}};

I want to fit these data with a quadratic equation, like this:

Fit[data, {1, x}, x]

Mathematica then outputs $1.5 + 1.4x$. However, trying to plot this like this:

Plot[Fit[data, {1, x}, x], {x, 0, 5}]

Results in the errors

General::ivar: 0.00010214285714285715` is not a valid variable.
General::ivar: 0.00010214285714285715` is not a valid variable.
General::ivar: 0.10214295918367347` is not a valid variable.
General::stop: Further output of General::ivar will be suppressed during this calculation.

I tried copying the $1.5 + 1.4x$ directly into Plot, after which I saw that it did not actually say $1.5 + 1.4x$:

Plot[1.5000000000000009` + 1.3999999999999995` x, {x, 0, 5}]

So that's where the ` came from. Surely removing them manually is not the way to go. What went wrong?

$\endgroup$
0

3 Answers 3

8
$\begingroup$

Plot has Attributes of HoldAll. This can be verified by:

Attributes@Plot 

{HoldAll, Protected, ReadProtected}

...from the second point under Details and Options in the Plot documentation:

Plot has attribute HoldAll and evaluates [the function] only after assigning specific numerical values to [the independent variable].

So in your example, we want to force Plot to evaluate the Fit function before attempting to create the graphics:

Plot[Evaluate@Fit[data, {1, x}, x], {x, 0, 5}]

enter image description here

and to combine with the data.

Show[{Plot[Evaluate@Fit[data, {1, x}, x], {x, 0, 5}], 
 ListPlot[data, PlotStyle -> ColorData[1, 2]]}]

or

Plot[Evaluate@Fit[data, {1, x}, x], {x, 0, 5}, Epilog -> {ColorData[1, 2], Point@data}]

enter image description here

As to your second point, when you copy the output of Fit and paste it into the front end, a real number approximation is shown based on $MachinePrecision.

$\endgroup$
1
5
$\begingroup$

You can use LinearModelFit like this:

data={{1,3},{2,4},{3,6},{4,7}};
lmf=LinearModelFit[data,x,x];
p1=Plot[lmf[x],{x,0,5}];
p2=ListPlot[data,PlotStyle->{PointSize@Large,Red}];
Show[p1,p2]

To get:

enter image description here

$\endgroup$
3
$\begingroup$

You could, of course, choose to use FindFit[] instead:

fitLine[x_] = a + b x /. FindFit[data, a + b x, {a, b}, x]

Plot[fitLine[x], {x, 0, 5}, Axes -> None,
     Epilog -> {Directive[AbsolutePointSize[6], Red], Point[data]}, Frame -> True]

points with best-fit line

This works, since FindFit[] returns a list of replacement rules for the coefficients:

FindFit[data, a + b x, {a, b}, x]
   {a -> 1.5, b -> 1.4}

You can then use ReplaceAll[] (/.) to replace the coefficients in a + b x with the numerical values found by FindFit[]. (I used Set[] instead of SetDelayed[] so that the replacement is instantly done before the function fitLine[] is defined.)

$\endgroup$
2
  • $\begingroup$ +1, however IMHO you should use formal symbols or add Block, or at least reference these methods. $\endgroup$
    – Mr.Wizard
    Jun 2, 2013 at 7:53
  • $\begingroup$ Hmm, maybe later... $\endgroup$ Jun 2, 2013 at 12:39

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