[当前]
我正在导入一个文本文件,其中第一列有模拟时间(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
[希望]
我需要在其上绘制一条平均线,如下图所示:
这是一个仅包含gnuplot的解决方案,包含样本数据:
set table "test.data"
set samples 1000
plot rand(0)+sin(x)
unset table
你应该查看gnuplot demo页面的平均值。我将在动态构建函数方面概括这个演示。这样可以更容易地更改平均值中包含的点数。
这是脚本:
# 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
这是结果:
平均值远远落后于算法预期的数据点。也许50分太多了。或者,可以考虑实施居中的移动平均线,但这超出了这个问题的范围。而且,我也认为你对外部程序更灵活:)
编辑
更新的问题是关于moving average。
根据this demo的说法,你可以单独用gnuplot以有限的方式做到这一点。
但在我看来,使用python或ruby等编程语言预处理数据会更灵活,并为您需要的任何移动平均值添加额外的列。
原始答案保留如下:
你可以使用fit
。看起来你想要适应恒定的功能。像这样:
f(x) = c
fit f(x) 'S1_delay_120_LT100_LU15_MU5.txt' using 1:2 every 5 via c
然后你可以绘制它们。
plot 'S1_delay_120_LT100_LU15_MU5.txt' using 1:2 every 5, \
f(x) with lines
请注意,这种技术可以与任意函数一起使用,而不仅仅是常量函数或线性函数。
这里有一些顶级答案的替代代码,这使得它也可以工作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))
我想评论Franky_GT,但不知何故stackoverflow没有让我。
但是,Franky_GT,你的答案很棒!
人们在绘制.xvg文件时的注释(例如,在对MD模拟进行分析之后),如果您不添加以下行:
set datafile commentschars "#@&"
Franky_GT的移动平均代码将导致此错误:
unknown type in imag()
我希望这对任何人都有用。
这是我的建议。它还需要gnuplot> = 5.2,因为它使用数据块和数组。它类似于@Franky_GT的答案,但也描述了如何将数据从数据块转换为数组。如果需要将文件中的数据导入数据块,可以使用:gnuplot: load datafile 1:1 into datablock。此外,可以选择用于平均的点数N
,并且它们居中并且x值不必是整数或等距。在我的旧电脑上需要约。 5000个数据点0.35秒,平均值超过250。
码:
### centered average over n values
reset session
set key top left
# create some test data
DataPoints = 5000
set print $Data
y0=0; x0=0
do for [i=1:DataPoints] { print sprintf("%g %g",x0=x0+rand(0),y0=y0+rand(0)-0.5) }
set print
TimeStart = time(0.0) # get start time
# put y-data into array
array A[|$Data|] # define size of array
set table $Dummy
plot $Data u (A[$0+1]=$2) w table # define array elements
unset table
print sprintf("Duration: %.3f sec",time(0.0)-TimeStart) # print elapsed time
N=250 # average over N datapoints
Start(n) = (start=int(n-N/2)) < 1 ? 1 : start
End(n) = (end=int(n+N/2)) > |$Data| ? |$Data| : end
Count(n) = End(n)-Start(n)+1
plot \
$Data u 1:2 w l title "Data curve", \
$Data u 1:((sum [i=Start($0+1):End($0+1)] A[i])/Count($0+1)) \
w l lw 2 lc rgb "red" t sprintf("Average over %d",N)
print sprintf("Duration: %.3f sec",time(0.0)-TimeStart) # print elapsed time
### end of code
结果: