14
$\begingroup$

As the question says, can one force a fit through the origin $(0,0)$, as one can when fitting a trendline to your data in Microsoft Excel? If so, how do you do that?

$\endgroup$
0

4 Answers 4

18
$\begingroup$
data = Table[{i, 3 i + RandomReal[2]}, {i, 10}]
line = Fit[data, {x}, x]
Show[ListPlot[data, PlotStyle -> Red], Plot[line, {x, 0, 10}], PlotLabel -> line]

Mathematica graphics

$\endgroup$
3
  • 12
    $\begingroup$ Also: LinearModelFit[..., IncludeConstantBasis -> False]. $\endgroup$ Commented Sep 17, 2012 at 19:00
  • $\begingroup$ @OleksandrR. also Minimize[Sum[(i[[2]] - a i[[1]])^2, {i, data}], a] and zillions more :) $\endgroup$ Commented Sep 17, 2012 at 19:08
  • 1
    $\begingroup$ Yes, that surely fits the description of "force"! :) $\endgroup$ Commented Sep 17, 2012 at 20:28
15
$\begingroup$

Another possibility, a bit more general :

data = Table[{i, 3 i + RandomReal[2]}, {i, 10}];

model[x_] = a Cos[x] + b x^2 + c;

sol = FindFit[data, {model[x]}, {a, b, c}, x];

One can add constraints on the parameters to the model :

sol2 = FindFit[data, {model[x], model[0] == 0}, {a, b, c}, x];

Show[ListPlot[data],  Plot[{model[x] /. sol, model[x] /. sol2}, {x, 0, 10}]]

plot

$\endgroup$
5
  • 8
    $\begingroup$ Important consideration with this approach: the interior point method (which is used for all constrained fits unless Method -> NMinimize is specified) requires that the residual and any additional constraints be twice differentiable, preferably analytically. If not, it will usually have trouble converging. $\endgroup$ Commented Sep 17, 2012 at 20:32
  • $\begingroup$ @OleksandrR. Good point, thanks, I was not aware of this - is it in the documentation ? $\endgroup$ Commented Sep 18, 2012 at 11:15
  • $\begingroup$ Sort of--you can find it discussed in relation to FindMinimum here. $\endgroup$ Commented Sep 18, 2012 at 11:26
  • $\begingroup$ @OleksandrR. Thanks. $\endgroup$ Commented Sep 18, 2012 at 11:50
  • $\begingroup$ Thank you all for answering. I really appreciate it. $\endgroup$ Commented Sep 20, 2012 at 10:16
7
$\begingroup$

I have given a derivation of the needed formulae in this math.SE answer. As already mentioned by belisarius, the canonical method for finding the equation of the least-squares line constrained to pass through the origin in Mathematica would be either of

Fit[data, {x}, x]

which produces the explicit linear function, or

FindFit[data, m x, m, x]

which produces just the slope of the best-fit line as a replacement rule.

To handle the case of a least-squares line constrained to pass through an arbitrary point $(h,k)$, you can again use either of Fit[] or FindFit[], but things are slightly trickier. (I'll leave the task of encapsulating that method in a Mathematica routine as an exercise.) For this answer, I'll present the explicit formula, as implemented in Mathematica:

fixedLine[data_?MatrixQ, pt : (_?VectorQ) : {0, 0}] := Module[{a, b, dat, sx, sy},
  dat = If[Precision[data] === Infinity, N[data], data];
  {sx, sy} = Transpose[dat] - pt;
  b = sx.sy/sx.sx;
  a = #2 - b #1 & @@ pt;
  Function[\[FormalX], Evaluate[Chop[a + b \[FormalX]]]]]

This returns the best-fit line as a pure function. Here are a few examples, taken from Kolb's Curve Fitting for Programmable Calculators:

fixedLine[{{100, 140}, {200, 230}, {300, 310}, {400, 400}, {500, 480}}, {300, 310}]
   Function[\[FormalX]$, 55. + 0.85 \[FormalX]$]

fixedLine[{{11, 15}, {17, 23}, {23, 31}, {29, 39}}]
   Function[\[FormalX]$, 1.34831 \[FormalX]$]
$\endgroup$
1
  • $\begingroup$ Thank you J.M. for answering my question. $\endgroup$ Commented Sep 20, 2012 at 10:16
7
$\begingroup$

belisarius gives the solution but forgot to tell why it is the solution.

The general equation for your linear regression line is

$y = a x + b$

which you write in the Fit function as

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

The second parameter is a list of functions. Fit will find the best fit by making a weighted sum of these functions, i.e.

$ a_1 \cdot x + a_2 \cdot 1 $

If you want a line through the origin the constant term should be zero, and the Fit becomes

line = Fit[data, {x}, x]

Example:

data = Table[{i, 10 + 3 i + RandomReal[2]}, {i, 10}];
line1 = Fit[data, {1, x}, x]
line2 = Fit[data, {x}, x]
Show[ListPlot[data, PlotStyle -> PointSize[0.02]], 
     Plot[{line1, line2}, {x, 0, 10}, PlotStyle -> Thick]]

gives us

11.673984 + 2.9005496 x  
4.5682616 x  

points and best-fit lines

$\endgroup$
1
  • $\begingroup$ Thank you very much stevenh for the clarification. $\endgroup$ Commented Sep 20, 2012 at 10:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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