[当前]
我正在导入一个文本文件,其中第一列具有仿真时间(0〜150),第二列具有延迟(0.01〜0.02)。
1.000000 0.010007
1.000000 0.010010
2.000000 0.010013
2.000000 0.010016
.
.
.
149.000000 0.010045
149.000000 0.010048
150.000000 0.010052
150.000000 0.010055
Run Code Online (Sandbox Code Playgroud)
[需要]
我需要在其上绘制一条平均线,如下图所示,并带有红线:
小智 7
这里有一些顶级答案的替换代码,这使得它也适用于 1000+ 点并且速度更快。我猜只适用于 gnuplot 5.2 及更高版本
# number of points in moving average
n = 5000
array A[n]
samples(x) = $0 > (n-1) ? n : int($0+1)
mod(x) = int(x) % n
avg_n(x) = (A[mod($0)+1]=x, (sum [i=1:samples($0)] A[i]) / samples($0))
Run Code Online (Sandbox Code Playgroud)
对于 gnuplot>=5.2,最有效的解决方案可能是使用像 @Franky_GT 的解决方案这样的数组。但是,它使用伪列 0(请参阅 参考资料help pseudocolumns)。如果您的数据中有一些双空行,$0则数据将被重置,0这可能会扰乱您的平均值。
该解决方案使用索引t来计算数据行和两个N大小的数组Y[]和X[]。后者适用于需要居中移动平均线的情况。数据点在 x 上不必等距。
脚本:(适用于 gnuplot>=5.2.0,2017 年 9 月)
### moving average over N points
reset session
# create some random test data
set table $Data
set samples 5000
y0 = 0
plot '+' u 0:(y0=y0+rand(0)*2-1) w table
unset table
# average over N values
N = 250
array X[N]
array Y[N]
AvgX(colX) = (X[t%N+1]=column(colX), n=(t<N ? t : N), (sum [i=1:n] X[i])/n)
AvgY(colY) = (Y[t%N+1]=column(colY), t=t+1, n=(t<N ? t : N), (sum [i=1:n] Y[i])/n)
plot $Data u 1:2 w l ti "Data", \
t=0 '' u 1:(AvgY(2)) w l lc rgb "red" ti "Moving average over ".N, \
t=0 '' u (AvgX(1)):(AvgY(2)) w l lw 2 lc rgb "green" ti "Moving average centered over ".N
### end of script
Run Code Online (Sandbox Code Playgroud)
结果:
这是带有示例数据的仅gnuplot解决方案:
set table "test.data"
set samples 1000
plot rand(0)+sin(x)
unset table
Run Code Online (Sandbox Code Playgroud)
您应该检查gnuplot演示页面以获取运行平均值。我将通过动态构建功能来概括该演示。这使得更改平均值中包含的点数变得更加容易。
这是脚本:
# number of points in moving average
n = 50
# initialize the variables
do for [i=1:n] {
eval(sprintf("back%d=0", i))
}
# build shift function (back_n = back_n-1, ..., back1=x)
shift = "("
do for [i=n:2:-1] {
shift = sprintf("%sback%d = back%d, ", shift, i, i-1)
}
shift = shift."back1 = x)"
# uncomment the next line for a check
# print shift
# build sum function (back1 + ... + backn)
sum = "(back1"
do for [i=2:n] {
sum = sprintf("%s+back%d", sum, i)
}
sum = sum.")"
# uncomment the next line for a check
# print sum
# define the functions like in the gnuplot demo
# use macro expansion for turning the strings into real functions
samples(x) = $0 > (n-1) ? n : ($0+1)
avg_n(x) = (shift_n(x), @sum/samples($0))
shift_n(x) = @shift
# the final plot command looks quite simple
set terminal pngcairo
set output "moving_average.png"
plot "test.data" using 1:2 w l notitle, \
"test.data" using 1:(avg_n($2)) w l lc rgb "red" lw 3 title "avg\\_".n
Run Code Online (Sandbox Code Playgroud)
结果如下:
平均值比算法预期的要晚很多数据点。也许50分太多了。或者,可以考虑实施集中移动平均线,但这超出了此问题的范围。而且,我还认为您可以使用外部程序更加灵活:)
编辑
更新的问题是关于移动平均线的的。
根据此演示,您可以仅使用 gnuplot 以有限的方式完成此操作,您可以仅使用 gnuplot 以有限的方式完成此操作。
但在我看来,使用python或ruby 等编程语言预处理数据会更灵活并为您需要的任何类型的移动平均线添加额外的列会更灵活。
原答案保留如下:
您可以使用fit。看来你想适应一个常数函数。像这样:
f(x) = c
fit f(x) 'S1_delay_120_LT100_LU15_MU5.txt' using 1:2 every 5 via c
Run Code Online (Sandbox Code Playgroud)
然后你可以绘制它们。
plot 'S1_delay_120_LT100_LU15_MU5.txt' using 1:2 every 5, \
f(x) with lines
Run Code Online (Sandbox Code Playgroud)
请注意,该技术可用于任意函数,而不仅仅是常数或线性函数。