如何用gnuplot对C代码生成数据的归一化直方图进行拟合
用Gnuplot实现直方图归一化与分布拟合
我来一步步帮你搞定这个问题——从直方图归一化到指定分布的拟合,咱们结合你现有的Gnuplot代码来调整:
第一步:实现直方图归一化
你原来的代码画的是频数直方图(每个箱子的高度是数据点数量),归一化需要把它转换成概率密度直方图(所有箱子的面积之和为1),步骤如下:
- 先获取数据总条数:在Gnuplot里用
stats命令读取数据文件,它会自动统计总记录数:
stats "out.dat"
执行后,总数据数会存在STATS_records变量里。
- 修改直方图的y轴计算逻辑:把原来的
(1.0)改成1.0/(STATS_records*width),这样每个箱子的高度就变成了概率密度(高度×宽度=该区间的概率)。
修改后的完整归一化直方图代码:
width = 5000 hist(x,width)=width*floor(x/width)+width/2.0 # 计算每个箱子的中心位置 set boxwidth width set style fill solid 0.5 set xrange [0:500000] # 这里不再固定yrange,让Gnuplot自动适配归一化后的数值 set yrange [0:*] stats "out.dat" # 统计总数据数 plot "out.dat" u (hist($1,width)):(1.0/(STATS_records*width)) smooth freq w boxes lc rgb"green" title "归一化直方图"
第二步:拟合指定分布函数
接下来咱们把归一化后的直方图拟合到你需要的分布(比如正态分布、指数分布),这里以正态分布为例,步骤如下:
- 定义你要拟合的分布函数:
# 正态分布概率密度函数:mu是均值,sigma是标准差,A是归一化系数 norm(x, mu, sigma, A) = A * exp(-(x-mu)**2/(2*sigma**2))
如果是拟合指数分布,可以改成:
# 指数分布概率密度函数:lambda是率参数,A是归一化系数 exp_dist(x, lambda, A) = A * exp(-lambda*x)
- 使用
fit命令让Gnuplot自动拟合参数:
# 拟合正态分布,初始值可以根据数据大概估计(比如mu设为数据均值,sigma设为标准差) fit norm(x, 250000, 100000, 1e-6) "out.dat" u (hist($1,width)):(1.0/(STATS_records*width)) smooth freq via mu, sigma, A
这里的初始值(250000, 100000, 1e-6)可以根据你的数据分布调整,让拟合更快收敛。
- 同时画出直方图和拟合曲线:
plot "out.dat" u (hist($1,width)):(1.0/(STATS_records*width)) smooth freq w boxes lc rgb"green" title "归一化直方图", \ norm(x, mu, sigma, A) lc rgb"red" lw 2 title "拟合正态分布"
完整的拟合示例代码(正态分布)
width = 5000 hist(x,width)=width*floor(x/width)+width/2.0 set boxwidth width set style fill solid 0.5 set xrange [0:500000] set yrange [0:*] set title "归一化直方图与正态分布拟合" set xlabel "数据值" set ylabel "概率密度" # 统计数据总条数 stats "out.dat" # 定义正态分布函数 norm(x, mu, sigma, A) = A * exp(-(x-mu)**2/(2*sigma**2)) # 拟合参数,设置初始值 fit norm(x, 250000, 100000, 1e-6) "out.dat" u (hist($1,width)):(1.0/(STATS_records*width)) smooth freq via mu, sigma, A # 绘制直方图和拟合曲线 plot "out.dat" u (hist($1,width)):(1.0/(STATS_records*width)) smooth freq w boxes lc rgb"green" title "归一化直方图", \ norm(x, mu, sigma, A) lc rgb"red" lw 2 title sprintf("拟合正态分布 (μ=%.0f, σ=%.0f)", mu, sigma)
如果你要拟合其他分布,只需要替换分布函数的定义和fit命令里的函数名、参数即可。
内容的提问来源于stack exchange,提问作者Lê Dũng
相关产品推荐
相关产品推荐

