Skip to content

Commit a100ffc

Browse files
author
Marek P
committed
More robust polyfit
Hello, during some work I found the results of polyfit unnecessarily inaccurate. I have found out, that lsq system matrix is constructed via x.^n (which supposedly walks through log/exp pow), and also the A\y inversion did not work to expectations, compared to other numerical tools. Below, see link to a test data file. x=readdlm("polyfit_8th_order_test.dat"); p=polyfit(x[:,1], x[:,2], 8); plot(x[:,2]-p(x[:,1]) -- a huge difference between previous (meaningless result) and patched version. (And yes, the 8th order is physical in this data set ;-)) https://github.com/Keno/Polynomials.jl/files/659739/polyfit_8th_order_test.dat.zip
1 parent 6bb8e2e commit a100ffc

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

src/Polynomials.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,13 +541,29 @@ polyfit(xs, ys, 2)
541541
```
542542
543543
Original by [ggggggggg](https://github.com/Keno/Polynomials.jl/issues/19)
544+
More robust version by Marek Peca <[email protected]>
545+
(1. no exponentiation in system matrix construction, 2. QR least squares)
544546
"""
545547
function polyfit(x, y, n::Int=length(x)-1, sym::Symbol=:x)
546548
length(x) == length(y) || throw(DomainError)
547549
1 <= n <= length(x) - 1 || throw(DomainError)
548550

549-
A = [ float(x[i])^p for i = 1:length(x), p = 0:n ]
550-
Poly(A \ y, sym)
551+
#
552+
# here unsure, whether zeros(Float64), or similar(x,...)
553+
# however similar may yield unwanted surprise in case of e.g. x::Int
554+
#
555+
A=zeros(Float64, length(x), n+1)
556+
#
557+
# TODO: add support for poly coef bitmap
558+
# (i.e. polynomial with some terms fixed to zero)
559+
#
560+
A[:,1]=1
561+
for i=1:n
562+
A[:,i+1]=A[:,i] .* x # cumulative product more precise than x.^n
563+
end
564+
Aqr=qrfact(A) # returns QR object, not a matrix
565+
p=Aqr\y # least squares solution via QR
566+
Poly(p, sym)
551567
end
552568
polyfit(x,y,sym::Symbol) = polyfit(x,y,length(x)-1, sym)
553569

0 commit comments

Comments
 (0)