使用gnuplot从时间序列图中的文件中的数据绘制垂直线

时间:2016-01-30 18:50:09

标签: bash gnuplot

我目前正在开展一个项目,以便在我的地方绘制湿度和温度的变化。因此我使用Raspbian Jessie和DHT-22的树莓派2。

最后它归结为每天一个文件,它将测量值全部存储30秒。该文件的名称如下; 2016-01-30_Temp_Hum_data并包含以下数据

2016-01-30-19:30:03 22.0 50.2
2016-01-30-19:30:34 22.0 50.2
2016-01-30-19:31:04 22.0 50.3
2016-01-30-19:31:35 22.0 50.3
2016-01-30-19:32:05 22.0 50.2

而第一部分是时间戳,第二部分用空格分隔的是温度,然后是湿度。

现在我用以下脚本绘制它,该脚本由bash文件中的for循环调用,该文件迭代我上面描述的所有数据文件。

!/usr/bin/gnuplot
reset

# This command works for a linux computer. In linux, you need to specify the exact location of
# the font you want to use
set terminal png notransparent rounded giant font "/usr/share/fonts/msttcore/arial.ttf" 24 \
  size 2600,960

# nomirror means do not put tics on the opposite side of the plot
set xtics nomirror
set ytics nomirror

# Line style for axes
# Define a line style (we're calling it 80) and set
# lt = linetype to 0 (dashed line)
# lc = linecolor to a gray defined by that number
set style line 80 lt 0 lc rgb "#808080"

# Line style for lines
set style line 1 lt 1 lc rgb "#A00000" lw 4
set style line 2 lt 1 lc rgb "#00A000" lw 4

# Add line at 70
# Draw a line from the right end of the graph to the left end of the graph at
# the y value of 70
# The line should not have an arrowhead
# Linewidth = 4
# Linecolor = black
# It should be in front of anything else drawn
set arrow from graph 0,first 70 to graph 1, first 70 nohead lw 2 lc rgb "#500000" front
set arrow from graph 0,first 50 to graph 1, first 50 nohead lw 2 lc rgb "#005000" front
set arrow from graph 0,first 20 to graph 1, first 20 nohead lw 2 lc rgb "#005000" front

# Put a label 80% hum at 80% the width of the graph and y = -2 (it will be just above the line drawn)
set label "70%" at graph 0.8, first 72
set label "50%" at graph 0.8, first 48
set label "20°C" at graph 0.8, first 22

# Define data
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%H"
set xlabel "time"

set ylabel "values"
set yrange [10:80]

heading="Kueche Temperatur und Luftfeuchtigkeit " . timestamp
set title heading
set key reverse Left outside
set grid

set style data lines

plot datafile  using 1:2 ls 1 title "",datafile  using 1:3 ls 2 title ""

它的效果非常好,但现在我每次开始做饭或洗衣机时都会制作一个节点并制作如下文件:

2016-01-30-15:00:00 cooking
2016-01-22-19:00:00 washing machine
2016-01-23-12:30:00 washing machine

现在我想添加以下功能。如果烹饪/清洗文件中的条目落在图表的x范围内,我想要从图的底部到顶部的垂直线,并带有“烹饪”或“洗衣机”的注释。

不幸的是,我甚至没有在某个时刻获得垂直线。我试过了     set arrow from 15,0 to 15,100 nohead lw 2 lc rgb "#500000" front 和     set arrow from 2016-01-30-19:00:00,0 to 2016-01-30-19:00:00,100 no head lw 2 lc rgb "#500000" front 以及我在网上找到的其他一些例子,但没有任何效果。

有人可以帮我找到一种方法吗

  1. 至少在我的时间序列图上绘制一条垂直线
  2. 或者甚至更好,告诉我如何自动检测附加文件中是否有一个点落入实际绘图的x范围并根据该文件添加垂直线?
  3. 提前致谢!!

1 个答案:

答案 0 :(得分:8)

我不会在这里重现你的整个剧本,而是专注于你要问的部分 - 添加垂直线。

我会在图表顶部添加标签,这样做需要添加一些额外的上边距以使其合适。如果将它们放在图表中,则不需要额外的上边距。此外,当您修复了yrange时,绘制垂直线会更容易。我们仍然可以在不这样做的情况下完成这项工作,但是我们要么需要创建一个绘图,找出它使用的yrange,然后使用该计算的yrange绘制新的绘图,或者使用stats命令来计算它(我们实际上稍后将需要stats命令来找出xrange)。我们通过固定的yrange来避免这种情况。

我需要证明这一点的最小设置如下:

set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%m/%d"
set yrange [10:80]
set tmargin at screen .9
unset key

当您将其编入完整脚本时,您可以添加其他详细信息(标题,轴标签等)。我还更改了x轴标签,以清楚地表明线条是在正确的位置绘制的(您将使用原始标签)。您可能需要调整标题的偏移量以避免线标签与标题之间发生冲突。

最后,我们可以绘制垂直线和标签(您需要将它与现有的绘图命令结合起来)

plot datafile u 1:(10):(0):(70) with vectors nohead,\ 
    "" u 1:(80):2 with labels offset 0,char 1.1 rotate by 45

我们使用矢量样式(help vectors),它需要四个值:x,y,x_delta和y_delta。由于我们需要垂直线,我们将x_delta设置为0,当我们从底部(y = 10)到顶部(y = 80)时,我们可以将y设置为10,将y_delta设置为70(80-10)。

标签当然要简单得多。在这里,我们将标签放在图表的顶部(向上移动1.1个字符以将其放置在图表上方)并旋转以避免重叠标签。

enter image description here

不幸的是,这里有一个问题。垂直行文件的范围可能会使从原始文件确定的范围变得混乱。这可以通过使用stats命令然后修复范围来修复。 stats命令不喜欢时间序列数据,但我们可以手动将时间序列解析为第一个步骤(set xdata time之前)。

如果我们将以下两个命令放在脚本的最顶层

stats datafile u (strptime("%Y-%m-%d-%H:%M:%S",strcol(1))) nooutput
set xrange[STATS_min:STATS_max]

它将根据数据文件中的范围修复xrange,因此我们没有这个问题。

您的原始示例数据与您为绘制垂直线所提供的数据没有任何重叠。为了证明这一点,我在数据文件的开头添加了一行,

2016-01-30-12:30:03 30.0 70.2

迫使那里重叠。因此,采用原始脚本,在开头添加这些额外命令(stats和xrange),并将两个新的plot命令添加到现有的plot命令(现在读取

plot datafile1 using 1:2 ls 1 title "",\
     ""  using 1:3 ls 2 title "", \
     datafile2 u 1:(10):(0):(70) with vectors nohead title "",\
     "" u 1:(80):2 with labels offset 0,char 1.1 rotate by 45 title ""

),我们获得

enter image description here

我这里没有使用你的set terminal命令,因此字体可能看起来不同。您可能需要对尺寸和偏移进行一些调整,以生成您满意的最终图,但这会增加您的原始要求。我也没有在这里添加额外的余量,因为标题会自动执行此操作。但是,如果您需要向上移动标题以避开标签(我在本例中没有这样做),您可能需要添加一些额外的保证金。