Gnuplot:x 轴上的多个标签

Gnuplot: multiple lables on x axis

我正在尝试绘制以下数据

29.07.2012 18:45:04;23.6;54
29.07.2012 18:50:04;22.7;56
29.07.2012 18:55:04;22.2;56
29.07.2012 19:00:04;22.0;56
29.07.2012 19:05:04;21.9;57
29.07.2012 19:10:04;21.8;56
29.07.2012 19:15:04;21.8;54
29.07.2012 19:20:04;21.7;53
29.07.2012 19:25:04;21.7;53

(日期、时间、温度、湿度)采用以下样式(在顶部裁剪):

x 轴上的标签是一天中的小时,下方是工作日和日期。我的数据文件中没有工作日,但我希望日期低于小时数。

我的剧情文件:

set datafile separator ";"
set terminal png size 5280,1024
set output '~/tfd.png'
set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"
set format x "%H"
plot "data.csv" using 1:2 title 'temperatur'

我可以想到三种方法来做到这一点。如果您不必将这些日期放在同一个轴上,则第二种方法可能是最稳定的。第一种和第三种方法各有优缺点。在这两者之间,第三种方法可能更好,但它需要更多的工作。

对于这些示例,为了确保数据跨越 1 天以上,我使用了您的相同数据,但多加了一行

31.07.2012 19:30:04;22.7;53

这三种方法都适用于 5.0 版。

方法 1 在 4.6 版中不正确,但可以通过一个额外的命令来实现。

方法 2 应该适用于任何合理的最新版本。

由于迭代中的溢出错误,方法 3 不会在 4.6 版中放置所有日期标签(有关某些解释,请参阅 ),但可以通过更改迭代来放置标签来使其工作。

方法 1 - 多图

我们可以通过使用多图将相同的图叠加在其自身上并每次做 x-axis 不同来做到这一点。

set datafile separator ";"
set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"

# Increase bottom margin to allow room for dates
set bmargin at screen 0.1

set multiplot layout 1,1
    # tics starting at 0 every 6 hours showing hour
    set xtics 0,60*60*6 format "%H"
    plot "data.csv" using 1:2 with lines t "Temperature"

    # Tics starting at 0 every 24 hours showing day.month
    # moved down by 1 character to be under hours
    set xtics 0,60*60*24 format "%d.%m" offset 0,-1
    set origin 0,0 # This is not needed in version 5.0
    replot
unset multiplot

除了坐标轴标签的不同之外,图表必须完全相同,以免它们不对齐,这确实会导致 y-axis 标签在覆盖自身时略微加粗。

在 5.0 版中不需要 set origin 命令,但在 4.6 版中需要。

方法 2 - 辅助轴

如果可以使用辅助轴,您也可以这样处理。例如,如果日期显示在 x2 轴上,小时显示在 x1 轴上,我们可以做

set datafile separator ";"
set xdata time
set x2data time
set timefmt "%d.%m.%Y %H:%M:%S"
set xtics 0,60*60*6 format "%H"
set x2tics 0,60*60*24 format "%d.%m"
plot "data.csv" using 1:2 with lines t "Temperature"

这消除了多图方法的一些问题,但导致两个数据标签位于不同的轴上。

方法 3 - 设置手动标签

终于可以手动设置标签了。幸运的是,我们可以在最新版本的 gnuplot 中使用循环,因此我们不必为其发出单独的命令,但我们必须自己计算标签。

我们可以使用 stats 命令来计算标签。如果我们给它时间数据,stats 命令会报错,所以我们必须在设置时间模式之前使用它,并且我们必须做一些计算日期边界的工作。为了确保我们处理的是每天的开始而不是中间的某个时间,我们将日期解析为内部表示(自 Unix 纪元以来的秒数),并向下舍入到最接近的 86400 的倍数(秒数一天内)。

我们可以做到

# in-large margin for date labels
set bmargin at screen 0.1
set datafile separator ";"

# Get first and last day in data file as STATS_min and STATS_max
stats "data.csv" u (floor(strptime("%d.%m.%Y %H:%M:%S",stringcolumn(1))/86400)*86400) nooutput

set xdata time
set timefmt "%d.%m.%Y %H:%M:%S"

set for [i=STATS_min:(STATS_max+86400):86400] label strftime("%d.%m",i) at i,graph 0 center offset 0,char -2

# set xtics every 6 hours
set xtics 0,60*60*6 format "%H"
plot "data.csv" using 1:2 with lines t "Temperature"

如果以后需要删除标签,我们可以通过对标签进行编号来改进这一点((i-STATS_min)/86400+1 会将它们编号为 1、2、3 等)。请注意,与第一种方法一样,我们需要增加底部的边距大小。我在标签上多加了一天,以涵盖 gnuplot 可能对 x-axis.

进行的舍入

在 4.6 版本中存在一个处理迭代和整数溢出的错误。要在 4.6 中使用此解决方案,请更改

set for [i=STATS_min:(STATS_max+86400):86400] label strftime("%d.%m",i) at i,graph 0 center offset 0,char -2

days = (STATS_max-STATS_min)/86400+1
set for [i=0:days] label strftime("%d.%m",i*86400+STATS_min) at (i*86400+STATS_min),graph 0 center offset 0,char -2