Polyfit isn't returning linear gradient and intercept

5 views (last 30 days)
testx = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
testx = 1×10
1 2 3 4 5 6 7 8 9 10
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
testy =[4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
testy = 1×10
4 6 8 10 12 14 16 18 20 22
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[PolyCoeff, S, mu] = polyfit(testx, testy, 1)
PolyCoeff = 1×2
6.0553 13.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
S = struct with fields:
R: [2×2 double] df: 8 normr: 7.9936e-15 rsquared: 1
mu = 2×1
5.5000 3.0277
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
So my question is - why isn't PolyCoeff returning (1) as 2, and (2) as 2? Where are 6 and 13 coming from? am I missing something really silly and obvious?

Accepted Answer

dpb
dpb on 3 Aug 2025
testx = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
testx = 1×10
1 2 3 4 5 6 7 8 9 10
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
testy =[4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
testy = 1×10
4 6 8 10 12 14 16 18 20 22
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[PolyCoeff] = polyfit(testx, testy, 1)
PolyCoeff = 1×2
2.0000 2.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
What you're missing is that according to the documentation for polyfit, when you ask for the optional third output of the mean,
[p,S,mu] = polyfit(x,y,n) also returns mu, which is a two-element vector with centering and scaling values. mu(1) is mean(x), and mu(2) is std(x). Using these values, polyfit centers x at zero and scales it to have unit standard deviation,
  4 Comments
Jolene
Jolene on 3 Aug 2025
This is really clear, thanks so much for taking the time.
dpb
dpb on 4 Aug 2025
Edited: dpb on 4 Aug 2025
"...I didn't realise that meant it would also retroactively change the coefficient output. "
Oh, sorry. I see @Torsten already responded, but I'll add aonther comment.
testx = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
testy = [4, 6, 8, 10, 12, 14, 16, 18, 20, 22];
testz = zscore(testx) % standardize the independent variable
testz = 1×10
-1.4863 -1.1560 -0.8257 -0.4954 -0.1651 0.1651 0.4954 0.8257 1.1560 1.4863
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[mean(testz) std(testz)]
ans = 1×2
0 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
and, indeed, as advertised mean, std deviation.
Now,
polyfit(testz,testy,1) % fit vs z instead of vs x
ans = 1×2
6.0553 13.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
and you see you get the coefficients returned by polyfit in the three-output case. It is the same as if the coefficients were scaled after fitting y vs x but polyfit actually uses the z-score values as the independent variable to improve numerical precision for higher-order polynomials, This is shown in the Alogorithms section of the documentation.
"I will have to read and understand documentation more closely in future! I took that it was such a basic function for granted!"
<LOL> Yes, Mathworks works very diligently to ensure that computations are as accurate as possible so what seems trivial on the surface may have very in-dpeth implementation consequences.
In the case of polyfit being one of the historical functions that has been included since the very early days, its implementation if beginning today would be unlikely to have this behavior at the user level of changing the algorithm based on the expected return variable(s) but would be implemented with named parameter pairs to control the behavior. But, it remains as is for backward compatibility.

Sign in to comment.

More Answers (0)

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!