【问题标题】:Gnuplot smoothing data in loglog plotloglog 图中的 Gnuplot 平滑数据
【发布时间】:2021-06-15 18:02:24
【问题描述】:

我想根据一个数据集绘制一条平滑曲线,该数据集在 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 的情况下将平滑应用于较低数据点的任何想法(无论如何都不起作用......)?

谢谢和最好的问候! JP

【问题讨论】:

  • 你能发布一些显示问题的数据吗?

标签: gnuplot spline smoothing loglog


【解决方案1】:

据我了解,gnuplot 中的采样是线性的。我不知道,但也许 gnuplot 中有一个我还没有找到的对数采样。

这里有一个解决方法的建议,它还不完美,但可以作为一个起点。 这个想法是将您的数据拆分为几十年,并分别对其进行平滑处理。 缺点是范围之间可能存在一些重叠。当您使用set samplesevery ::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,他指出可以通过简单地将整个范围映射到线性空间来简化它。与@maij 的解决方案相比,我会让 gnuplot 处理对数轴,并通过一些表格图的额外努力使实际的绘图命令尽可能简单。

代码:

### 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($1)):(log10($2)) smooth csplines
set table $Smoothed
    plot $SmoothedLog u (10**$1):(10**$2) 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 table $Smoothed 替换为set table 并查看原始数据,这真的是您所解释的吗?
【解决方案2】:

使用对数刻度基本上意味着绘制一个值的对数而不是值本身。 set logscale 命令告诉 gnuplot 自动执行此操作:

  1. 读取数据,还是线性世界,还没有对数
  2. 在等距网格 (smooth csplines) 上计算样条曲线,仍然是线性世界
  3. 计算并绘制对数 (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 (https://stackoverflow.com/a/66690491)
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($1)):(log10($2)) w p pt 7 ti "Data" ,\
     $Data u (log10($1)):(log10($2)) ti "cspline" smooth cspline

这是结果:

【讨论】:

  • 是的,就是这样。通过对数转换到线性空间是要走的路。虽然,我会让 gnuplot 处理对数刻度轴并简化实际的绘图命令。我将根据您的解决方案在我的答案中添加另一个建议。
  • @theozh 但我认为我的假设和以下解释是错误的。如果我这样做set logscale x; set logscale y; set table; plot $Data u 1:2 smooth cspline; unset table,那么看起来 gnuplot 正在正确处理日志平滑。我应该早点检查一下。现在我很困惑。我需要显示问题的原始数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多