假设我有一组点x,y
来绘制带有gnuplot的图像。它按预期工作,我得到一个很好的曲线。我想重复实验的大型图像数据集(比如1000) 。在这一点上,你会在一个图上得到1000条曲线,每条曲线对应一幅图像。我如何告诉gnuplot绘制曲线的最佳曲线?
我希望gnuplot能够在csv中给出最佳拟合曲线的x,y
点,因为我打算稍后会有一个最佳拟合图。
可以找到数据here
答案 0 :(得分:2)
如果我理解正确,你想要通过数据绘制平均线,而不是拟合数据的功能。您可以使用plot命令的smooth
选项执行此操作。
根据您的需要,您可以通过数据绘制插值函数。例如:
plot \
"libjpeg-2000-bench.png.csv" u 3:5 w p, \
"libjpeg-2000-mural.png.csv" u 3:5 w p, \
"libjpeg-2000-red-room.png.csv" u 3:5 w p, \
"libjpeg-bench.png.csv" u 3:5 w p, \
"libjpeg-mural.png.csv" u 3:5 w p, \
"libjpeg-red-room.png.csv" u 3:5 w p, \
"< tail -q -n +4 libjpeg*csv" u 3:5 smooth acsplines w l lw 2
给出
您可能想要尝试各种平滑功能,请参阅help smooth
。其中一些功能也采用其他参数。例如,您可以为acsplines
插值指定权重:
plot \
"libjpeg-2000-bench.png.csv" u 3:5 w p, \
"libjpeg-2000-mural.png.csv" u 3:5 w p, \
"libjpeg-2000-red-room.png.csv" u 3:5 w p, \
"libjpeg-bench.png.csv" u 3:5 w p, \
"libjpeg-mural.png.csv" u 3:5 w p, \
"libjpeg-red-room.png.csv" u 3:5 w p, \
"< tail -q -n +4 libjpeg*csv" u 3:5:(100) smooth acsplines title "acsplines, weight = 100" w l lw 2, \
"< tail -q -n +4 libjpeg*csv" u 3:5:(0.1) smooth acsplines title "acsplines, weight = 0.1" w l lw 2
权重的选择需要权衡:如果权重很大,那么曲线将更紧密地跟随数据点,但可能会出现振荡。
或者,您可以在x方向上对数据点进行分级,并对属于同一个bin的数据点进行平均。幸运的是,你可以在gnuplot中完成所有这些:
round(x) = floor(x+0.5)
bin(x,binwidth) = binwidth*round(x/binwidth)
binwidth = 1.
plot \
"libjpeg-2000-bench.png.csv" u 3:5 w p, \
"libjpeg-2000-mural.png.csv" u 3:5 w p, \
"libjpeg-2000-red-room.png.csv" u 3:5 w p, \
"libjpeg-bench.png.csv" u 3:5 w p, \
"libjpeg-mural.png.csv" u 3:5 w p, \
"libjpeg-red-room.png.csv" u 3:5 w p, \
"< tail -q -n +4 libjpeg*csv" u (bin($3,binwidth)):5 smooth uniq w l lw 2
给出
您可以在此根据需要调整binsize binwidth
。
答案 1 :(得分:1)
我必须承认,我并不完全清楚你想要达到什么目标,但我还有一种感觉,正如@KevinBoone在评论中所提到的那样,你正试图对其进行某种分类统计。数据。如果是这种情况,那么遗憾的是Gnuplot不适合执行此任务。在我看来,将这个处理任务委托给更合适的事情会更加实际。
作为一个例子,让我们说战略确实是:
为此,可以根据需要准备一个简短的Python脚本(实现上述步骤) scipy工具包提供的binned_statistic函数。所需的bin数作为第一个参数传递,而其余的参数被解释为csv文件进行处理:
#!/usr/bin/env python
import sys
import numpy as np
from scipy.stats import binned_statistic
num_of_bins = int(sys.argv[1])
data = []
for fname in sys.argv[2:]:
with open(fname, 'r') as F:
for line_id, line in enumerate(F):
if line_id < 3: continue
cols = line.strip().split(',')
x, y = map(float, [cols[i] for i in [2, 3]])
data.append((x, y))
data = np.array(data)
stat, bin_edges, _ = binned_statistic(data[:, 0], data[:, 1], 'mean', bins = num_of_bins, range = None)
for val, (lb, ub) in zip(stat, zip(bin_edges, bin_edges[1:])):
print('%E,%E' % ( (lb+ub)/2, val ))
现在,在Gnuplot中,我们可以在外部调用此脚本(假设它作为stat.py
存储在当前工作目录中)并将其与各个文件一起绘制:
set terminal pngcairo enhanced
set output 'fig.png'
#get all csv files in current directory as a space-delimited string
files = system("ls *.csv | xargs")
#construct a "pretty" label from the file name
getLabel(fname)=system(sprintf('echo "%s" | gawk -F"-" "BEGIN{OFS=\"-\"} {NF=NF-2;print}"', fname))
set datafile separator ","
set key spacing 1.5
LINE_WIDTH = 1.25
plot \
for [filename in files] filename u 3:4 w l lw LINE_WIDTH t getLabel(filename), \
sprintf('<python ./stat.py 20 %s', files) w l lw 3*LINE_WIDTH lc rgb 'red' t 'average'
然而,正如@KevinBoone指出的那样,这个“平均”在你的具体环境中是否具有合理的数学意义是另一个问题......