如何使用gnuplot绘制穿过所有给定点序列的平滑曲线
如何在gnuplot中绘制穿过非单调x值所有点的平滑曲线
问题说明
假设我们有一组点序列,若要绘制穿过这些点的平滑曲线,原本以为绘图选项smooth可以实现该需求。
根据help smooth的说明:
语法:
smooth {unique | frequency | fnormal | cumulative | cnormal | bins | kdensity {bandwidth} | csplines | acsplines | mcsplines | bezier | sbezier | unwrap}
其中Bézier曲线不会穿过原始数据点,部分splines(样条曲线)可以做到。但gnuplot中的splines要求x值为单调序列,若x值非单调,gnuplot会自动将其处理为单调序列,得到不符合预期的结果。
测试代码
### 尝试用smooth选项绘制过点平滑曲线 reset session set size ratio -1 $Data <<EOD 0 0 2 3 4 2 9 3 5 7 3 6 4 5 5 5 4 4 1 6 1 4 3 10 EOD set key out set ytics 1 plot $Data u 1:2 w lp pt 7 lc "red" dt 3 ti "data", \ '' u 1:2 w l smooth bezier lc "green" ti "bézier", \ '' u 1:2 w l smooth csplines lc "orange" ti "csplines", \ '' u 1:2 w l smooth mcsplines lc "magenta" ti "mcsplines", \ '' u 1:2 w l smooth acsplines lc "yellow" ti "acsplines" ### end of code
运行结果:所有smooth选项都无法得到符合预期的结果
解决方案
实现原理
gnuplot内置的smooth样条方案默认会对x轴值做单调排序处理,因此无法直接应用在x非单调的离散点序列上。我们可以引入虚拟参数t,t取值为原始点的顺序序号,分别对x(t)、y(t)做样条插值,再将插值后的(x,y)坐标串联起来,即可得到按原始点顺序穿过所有点的平滑曲线。
可运行代码
### 绘制穿过所有非单调点的平滑曲线 reset session set size ratio -1 $Data <<EOD 0 0 2 3 4 2 9 3 5 7 3 6 4 5 5 5 4 4 1 6 1 4 3 10 EOD # 统计原始数据点总数 stats $Data nooutput N = STATS_records # 分别对x(t)、y(t)做三次样条插值,t为行序号 set samples 500 # 插值采样数,数值越高曲线平滑度越高 set table $SplineX plot $Data u (column(0)):1 smooth csplines unset table set table $SplineY plot $Data u (column(0)):2 smooth csplines unset table # 合并插值得到的x、y坐标,生成平滑曲线数据集 set table $SmoothCurve plot $SplineX u 2:($SplineY[$0+1][2]) w l unset table set key out set ytics 1 plot $Data u 1:2 w lp pt 7 lc "red" dt 3 ti "原始数据", \ $SmoothCurve u 1:2 w l lc "blue" lw 2 ti "过点平滑曲线" ### end of code
效果说明
运行上述代码得到的蓝色曲线会严格穿过所有红色的原始数据点,且完全遵循原始点的输入顺序,不会出现x值非单调导致的曲线错乱问题。
内容的提问来源于stack exchange,提问作者theozh
相关产品推荐
相关产品推荐

