我开始使用 Gnuplot 并尝试了一些东西。现在,我想知道如何自动从拟合中删除异常值。图中显示了一个示例,其中数据点位于第二个数据集的 4,50 处。 以及数据集:
我发现了一个类似的问题here,但我无法让它适用于我的示例。可能有很多不同的方法,而且我对 Gnuplot 或类似软件没有那么丰富的经验。因此,我很高兴收到建议,描述异常值的可能方法是什么。
我在 Windows 10 上的 LaTeX (texlive) 中使用 gnuplottex 包。 gnuplot 代码:
\begin{gnuplot}[terminal=tikz, terminaloptions={color size 7cm,5cm}]
reset session
$Data <<EOD
#data
x y1 y2 y3 y4
1 1 6 4 2
2 4 10 1 1
3 9 15 0 0.5
4 16 50 1 2
5 25 31 4 5
6 36 42 9 12
7 49 55 30 23
EOD
datafile = 'data.dat'
set print 'parameters.dat'
#_____________Set the label for data points________________________
set key top left # set position of legend
set key Left # set raggedleft
set key samplen 2 spacing 1.2 font ",8" # set fontsize and spacing
set key noautotitle
###1__________Define function and number of columns_________________________
f(x,a,b,c) = a*(x-b)**2 + c
colMin = 2
colMax = 5
set fit quiet nolog
array A[colMax]
array B[colMax]
array C[colMax]
do for [col=colMin:colMax] {
a=1; b=1; c=4 # some initial values, sometimes 0 or NaN is not a good start
fit f(x,a,b,c) datafile u 1:col via a,b,c
A[col] = a; B[col] = b; C[col] = c
print sprintf ('%d %.4f %.4f %.4f',col-1,A[col],B[col],C[col])
}
plot for [col=colMin:colMax] datafile u 1:col ls col, \
for [col=colMin:colMax] f(x,A[col],B[col],C[col]) ls col, \
for [col=colMin:colMax] keyentry w lp ls col \
title sprintf("$y%d$",col-1)
\end{gnuplot}
正如评论中提到的,您必须以某种方式定义您认为的异常值。当然有几种方法可以做到这一点。我并不是说这是最好的方法,只是将其视为一个起点。
一些评论:
OutlierDist
您认为的异常值$NOOUTLIERS
,如果到拟合曲线的绝对距离是 >=OutlierDist
,则将 NaN
写入第二列,将原始值写入第三列。这当然可以优化。
数据:
"SO77774328.dat
x y1 y2 y3 y4
1 1 6 4 2
2 4 10 1 1
3 9 15 0 0.5
4 16 50 1 2
5 25 31 4 5
6 36 42 9 12
7 49 55 30 23
脚本:
### remove outliers for fitting
reset session
FILE = "SO77774328.dat"
PARAMS_1 = "SO77774328_1.par"
PARAMS_2 = "SO77774328_2.par"
f(x,a,b,c) = a*(x-b)**2 + c
colMin = 2
colMax = 5
set fit quiet nolog
array A[colMax]
array B[colMax]
array C[colMax]
set print PARAMS_1
do for [col=colMin:colMax] {
a=1; b=1; c=4 # some initial values, sometimes 0 or NaN is not a good start
fit f(x,a,b,c) FILE u 1:col via a,b,c
A[col] = a; B[col] = b; C[col] = c
print sprintf ('%d %.4f %.4f %.4f',col-1,A[col],B[col],C[col])
}
unset print
# write data to table with outliers --> NaN
OutlierDist = 10 # outlier distance
dev(colX,colY) = abs(column(colY)-f(column(colX),A[colY],B[colY],C[colY])-1) >= OutlierDist ? NaN : column(colY)
set table $NOOUTLIERS
do for [colY=colMin:colMax] {
plot FILE u 1:(v0=dev(1,colY)):(v0!=v0?column(colY):NaN) lc var
}
unset table
# fit again
set print PARAMS_2
do for [col=colMin:colMax] {
i = col-colMin # datablock index
a=1; b=1; c=4 # some initial values, sometimes 0 or NaN is not a good start
fit f(x,a,b,c) $NOOUTLIERS index i u 1:2 via a,b,c
A[col] = a; B[col] = b; C[col] = c
print sprintf ('%d %.4f %.4f %.4f',col-1,A[col],B[col],C[col])
}
unset print
set key noautotitle left top
plot for [col=colMin:colMax] FILE u 1:col ls col-1, \
for [col=colMin:colMax] f(x,A[col],B[col],C[col]) ls col-1, \
for [col=colMin:colMax] keyentry w lp ls col-1 title sprintf("y%d",col-1), \
$NOOUTLIERS u 1:(valid(2) ? NaN : column(3)) w p pt 6 ps 2 lc "red" ti "Outlier"
### end of script
结果: