[当前]
我正在导入一个文本文件,其中第一列有模拟时间(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
[希望]
我需要在其上绘制一条平均线,如下图所示,红线:
答案 0 :(得分:4)
以下是仅包含样本数据的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分太多了。或者,可以考虑实施居中的移动平均线,但这超出了这个问题的范围。 而且,我也认为你对外部程序更灵活:)
答案 1 :(得分:2)
修改强>
更新后的问题是moving average。
根据this demo,您可以仅使用gnuplot以有限的方式执行此操作。
但在我看来,使用python或ruby之类的编程语言对数据进行预处理会更灵活,并为您需要的任何移动平均线添加额外的列。 / p>
原始答案保留在下方:
您可以使用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
请注意,这种技术可以与任意函数一起使用,而不仅仅是常量函数或线性函数。
答案 2 :(得分:1)
这里是一些最佳答案的替换代码,这使它在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))
答案 3 :(得分:1)
我想对Franky_GT进行评论,但是不知何故stackoverflow不允许我这样做。
但是,Franky_GT,您的回答效果很好!
用于绘制.xvg文件的人员的注释(例如,在不对MD模拟进行分析之后),如果您未添加以下行:
set datafile commentschars "#@&"
Franky_GT的移动平均代码将导致此错误:
unknown type in imag()
我希望这对任何人都有用。
答案 4 :(得分:0)
这是我的建议。由于它使用数据块和数组,因此还需要 gnuplot> = 5.2 。它与@Franky_GT的答案类似,但也描述了如何将数据从数据块获取到数组中。
如果需要将文件中的数据放入数据块,则可以使用以下命令:gnuplot: load datafile 1:1 into datablock。
此外,可以选择要求平均的点N
的数量并将其居中,并且x值不必为整数或等距。
在我的旧PC上大约需要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
结果: