Gnuplot:x轴上的多个标签

时间:2016-01-24 22:22:23

标签: gnuplot

我试图绘制以下数据

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

(日期,时间,温度,湿度),格式如下(在顶部裁剪): enter image description here

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 个答案:

答案 0 :(得分:3)

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

对于这些示例,为了确保数据的传输时间超过1天,我使用了相同的数据,但又增加了一行

31.07.2012 19:30:04;22.7;53

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

方法1在版本4.6中没有正确排列,但可以使用一个额外的命令。

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

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

方法1 - 多重绘图

我们可以通过使用多重绘图将相同的图叠加在自身上并且每次都使x轴不同来实现。

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

enter image description here

除了轴标签的不同之外,图表必须相同,以避免它们没有排列,并且它确实会导致y轴标签在写入时略微加粗。

在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"

enter image description here

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

方法3 - 设置手动标签

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

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

enter image description here

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

版本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