Gnuplot 平滑 loglog 图中的数据
Gnuplot smoothing data in loglog plot
我想根据数据集绘制平滑曲线,该数据集在 x 中跨越 13 个数量级 [1E-9:1E4],在 y 中跨越 4 个数量级 [1E-6:1e-2]。
MWE:
set log x
set log y
set xrange [1E-9:1E4]
set yrange [1E-6:1e-2]
set samples 1000
plot 'data.txt' u 1:3:(1) smooth csplines not
x=10 以上的平滑曲线看起来不错。下面,它只是一条直线向下到 x=1e-9 的点。
当将样本增加到 1e4 时,平滑在 x=1 以上效果很好。对于样本 1e5,平滑在 x=0.1 以上效果很好,依此类推。
知道如何在不将样本设置为 1e10 的情况下对较低的数据点应用平滑(无论如何都不起作用...)吗?
谢谢并致以最诚挚的问候!
日本
据我了解,gnuplot 中的抽样是线性的。我不知道,但也许 gnuplot 中有一个我还没有找到的对数采样。
这里有一个解决方法的建议,它还不完美,但可以作为一个起点。
例如,我们的想法是将您的数据分成几十年,然后分别对它们进行平滑处理。
缺点是范围之间可能有一些重叠。当您使用 set samples
和 every ::n
时,您可以以某种方式最小化或隐藏它们,或者也许还有另一种方法可以消除重叠。
代码:
### smoothing over several orders of magnitude
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set samples 100
pMin = -9
pMax = 3
set table $Smoothed
myFilter(col,p) = (column(col)/10**p-1) < 10 ? column(col) : NaN
plot for [i=pMin:pMax] $Data u (myFilter(1,i)):2 smooth cspline
unset table
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 every ::3 w l ti "cspline"
### end of code
结果:
加法:
感谢@maij 指出可以通过简单地将整个范围映射到线性 space 来简化它。与@maij 的解决方案相反,我会让 gnuplot 处理对数轴,并通过一些 table 绘图的额外努力使实际绘图命令尽可能简单。
代码:
### smoothing in loglog plot
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set samples 500
set table $SmoothedLog
plot $Data u (log10()):(log10()) smooth csplines
set table $Smoothed
plot $SmoothedLog u (10**):(10**) w table
unset table
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set key top left
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 w l lc "red" ti "csplines"
### end of code
结果:
使用对数刻度基本上意味着绘制值的对数而不是值本身。 set logscale
命令告诉 gnuplot 自动执行此操作:
- 读数据,还是线性世界,还没有对数
- 在等距网格 (
smooth csplines
) 上计算样条,仍然是线性世界
- 计算并绘制对数 (
set logscale
)
重点是等距网格。假设选择 set xrange [1E-9:10000]
和 set samples 101
。在线性世界中 1e-9 与 10000 相比近似为 0,得到的网格将是 1E-9 ~ 0, 100, 200, 300, ..., 9800, 9900, 10000。第一个网格点在 0,第二个是 100,gnuplot 将在它们之间画一条直线。当之后绘制数字的对数时,这不会改变。
这就是您在问题中已经注意到的内容:您需要 10 倍以上的点才能获得较小指数的平滑曲线。
作为解决方案,我建议切换对数计算和样条曲线计算。
# create some random test data, code "stolen" from @theozh (
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
# this makes the splines smoother
set samples 1000
# manually account for the logarithms in the tic labels
set format x "10^{%.0f}" # for example this format
set format y "1e{%+03.0f}" # or this one
set xtics 2 # logarithmic world, tic distance in orders of magnitude
set ytics 1
# just "read logarithm of values" from file, before calculating splines
plot $Data u (log10()):(log10()) w p pt 7 ti "Data" ,\
$Data u (log10()):(log10()) ti "cspline" smooth cspline
这是结果:
我想根据数据集绘制平滑曲线,该数据集在 x 中跨越 13 个数量级 [1E-9:1E4],在 y 中跨越 4 个数量级 [1E-6:1e-2]。
MWE:
set log x
set log y
set xrange [1E-9:1E4]
set yrange [1E-6:1e-2]
set samples 1000
plot 'data.txt' u 1:3:(1) smooth csplines not
x=10 以上的平滑曲线看起来不错。下面,它只是一条直线向下到 x=1e-9 的点。
当将样本增加到 1e4 时,平滑在 x=1 以上效果很好。对于样本 1e5,平滑在 x=0.1 以上效果很好,依此类推。
知道如何在不将样本设置为 1e10 的情况下对较低的数据点应用平滑(无论如何都不起作用...)吗?
谢谢并致以最诚挚的问候! 日本
据我了解,gnuplot 中的抽样是线性的。我不知道,但也许 gnuplot 中有一个我还没有找到的对数采样。
这里有一个解决方法的建议,它还不完美,但可以作为一个起点。
例如,我们的想法是将您的数据分成几十年,然后分别对它们进行平滑处理。
缺点是范围之间可能有一些重叠。当您使用 set samples
和 every ::n
时,您可以以某种方式最小化或隐藏它们,或者也许还有另一种方法可以消除重叠。
代码:
### smoothing over several orders of magnitude
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set samples 100
pMin = -9
pMax = 3
set table $Smoothed
myFilter(col,p) = (column(col)/10**p-1) < 10 ? column(col) : NaN
plot for [i=pMin:pMax] $Data u (myFilter(1,i)):2 smooth cspline
unset table
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 every ::3 w l ti "cspline"
### end of code
结果:
加法:
感谢@maij 指出可以通过简单地将整个范围映射到线性 space 来简化它。与@maij 的解决方案相反,我会让 gnuplot 处理对数轴,并通过一些 table 绘图的额外努力使实际绘图命令尽可能简单。
代码:
### smoothing in loglog plot
reset session
# create some random test data
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
set samples 500
set table $SmoothedLog
plot $Data u (log10()):(log10()) smooth csplines
set table $Smoothed
plot $SmoothedLog u (10**):(10**) w table
unset table
set logscale x
set logscale y
set format x "%g"
set format y "%g"
set key top left
plot $Data u 1:2 w p pt 7 ti "Data", \
$Smoothed u 1:2 w l lc "red" ti "csplines"
### end of code
结果:
使用对数刻度基本上意味着绘制值的对数而不是值本身。 set logscale
命令告诉 gnuplot 自动执行此操作:
- 读数据,还是线性世界,还没有对数
- 在等距网格 (
smooth csplines
) 上计算样条,仍然是线性世界 - 计算并绘制对数 (
set logscale
)
重点是等距网格。假设选择 set xrange [1E-9:10000]
和 set samples 101
。在线性世界中 1e-9 与 10000 相比近似为 0,得到的网格将是 1E-9 ~ 0, 100, 200, 300, ..., 9800, 9900, 10000。第一个网格点在 0,第二个是 100,gnuplot 将在它们之间画一条直线。当之后绘制数字的对数时,这不会改变。
这就是您在问题中已经注意到的内容:您需要 10 倍以上的点才能获得较小指数的平滑曲线。
作为解决方案,我建议切换对数计算和样条曲线计算。
# create some random test data, code "stolen" from @theozh (
set print $Data
do for [p=-9:3] {
do for [m=1:9:3] {
print sprintf("%g %g", m*10**p, (1+rand(0))*10**(p/12.*3.-2))
}
}
set print
# this makes the splines smoother
set samples 1000
# manually account for the logarithms in the tic labels
set format x "10^{%.0f}" # for example this format
set format y "1e{%+03.0f}" # or this one
set xtics 2 # logarithmic world, tic distance in orders of magnitude
set ytics 1
# just "read logarithm of values" from file, before calculating splines
plot $Data u (log10()):(log10()) w p pt 7 ti "Data" ,\
$Data u (log10()):(log10()) ti "cspline" smooth cspline
这是结果: