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
我正在尝试绘制以下数据
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