Gnuplot: how to plot date / time chart - gnuplot

I would like to plot this kind of data:
X axis: dates
Y axis: time lenght
The data would looks like that:
22/02 51:10
25/02 63:10
01/03 50:55
23/03 52:10
I already done that for the X axis:
set xdata time
set timefmt "%d/%m"
But I don't know how to manage Y axis.

As Tom said, you can only use one timefmt. However, if it is possible to split your data to more columns like this:
22/02 51 10
25/02 63 10
01/03 50 55
23/03 52 10
you can then plot the time length by direct calculation, like this:
plot 'file' u 1:($2 + $3/60)
to plot minutes, or like this:
plot 'file' u 1:($2/60 + $3/3600)
to plot hours.

From ?xdata
There is currently only one timefmt,
which implies that all the time/date
columns must conform to this format.
So you need to alter your data somewhat to conform to one setting.
something like
00:00:22/02 51:10:22/02
00:00:25/02 63:10:22/02
00:00:01/03 50:55:22/02
00:00:23/03 52:10:22/02
Note that you can use command line tools to do this within gnuplot, see here
Once the file is edited you can read it like so
set xdata time
set ydata time
set timefmt "%M:%S:%d/%m"
set format x "%d/%m"
set format y "%M:%S"
plot "date_time.dat" u 1:2 w l

Related

Labeling Points with a date/time x axis in GNUPLOT

I have a simple dataset consisting of a date/time field (YYYY-MM-DD HH:MM) and a temperature field, taken at 1 minute intervals. I am trying to learn how to label points on a plot such than I can label the max and min temperatures.
The data is coming from an SQL server in a node.js app and the commands / data are being piped to gnuplot via STDIN with the output being a PNG. I can successfully plot the data, but now I am just trying to label the max and min temperature points on the plot, with the "coordinates" coming from an SQL query such that a min or max point would look like (x,y) = (2021-02-11 18:34, 72.57). Every command I try that should label points on the plot have no effect. And the examples that I find usually don't involve a date/time x-axis.
What is the magic ju-ju needed to be able to take an arbitrary data point and label it on the plot with a time/date x-axis? FWIW, since the data is being retrieved from an SQL server, I can format the data in whatever way makes it the easiest method needed to plot the data and more importantly, label the points that I want.
Thanks in advance for any advice!!
Justin
EDIT (per the first comment):
Here is what I am using in terms of gnuplot commands:
set term png size 1280,600
unset output
set datafile separator ","
set xdata time
set timefmt "%Y-%m-%d %H:%M"
set format x "%H:%M"
set ylabel "Temperature ˚F
set xlabel "Time
set style line 100 lt 1 lc rgb "grey" lw 0.5
set grid ls 100
set xtics border
set xtics rotate
set key off
$mydata << EOD
// this is where my code "prints" the SQL data to STDIN of gnuplot
// data is formatted: 2021-02-11 22:48,74.42
EOD
plot $mydata using 1:2 with lines
Note, I can format the data in whatever way that makes it easiest for gnuplot to process. I have found that sending YYYY-MM-DD HH:MM,TEMP has worked without issue.
I am tring to use the 'set label' command using a time/date as the x value and the temperature as the y value:
set label 1 'Maximum' at 2021-02-11 19:10,72.50
which does not produce any labels.
Here is an example plot where I want to label the max and min points:
When the x axis is time, the units are seconds. You are looking for the functions that convert between seconds (a floating point value) and a formatted time/date string.
strptime("timeformat",s) reads the time from the string s using the
timeformat specifiers and converts it into seconds since the year 1970.
strftime("timeformat",t) produces a string by applying the timeformat
specifiers to the time t
given in seconds since the year 1970.
In the case you show, this would correspond to:
myformat = "%Y-%m-%d %H:%M"
set label 1 'Maximum' at strptime(myformat, "2021-02-11 19:10"), 72.50

How to plot month numbers in gnuplot 5.4?

I am trying to get the month of a date in gnuplot 5.4.
Consider the following data:
2019/01/01
2019/02/01
2019/03/01
2019/04/01
2019/05/01
2019/06/01
2019/07/01
2019/08/01
2019/09/01
2019/10/01
2019/11/01
2019/12/01
2020/01/01
2020/02/01
2020/03/01
2020/04/01
2020/05/01
2020/06/01
2020/07/01
2020/08/01
2020/09/01
2020/10/01
2020/11/01
2020/12/01
For each data point, I want to show the full date on the x axis and the month number (0-11) on the y axis.
The gnuplot documentation recommends using the tm_mon function for such a task, which should return the month number for a given date.
As far as I understand, the following gnuplot script should do what I want:
#!/bin/gnuplot
set timefmt '%Y/%m/%d'
set xdata time
set format x '%m/%y'
set datafile separator ','
plot "data.csv" using 1:(tm_mon($1)) title 'data'
But that is not the case. This gnuplot script correctly shows dates on the x axis but has a constant 0 on the y axis.
What am I doing wrong? Why is tm_mon($1) constantly returning 0?
I'm not sure whether I fully got your intention.
I understand you want column 1 as xtic labels.
However, there is a difference between just taking the column 1 as xtic labels or interpreting column 1 as date/time and scaling the x-axis accordingly and gnuplot would take care automatically about the xtic labels.
For the first case, the width of the graph might not be wide enough to show all labels without overlap, so, I reformatted date. Check help strptime and help strftime. By the way, help tm_mon says it needs input in seconds, not in your date format as it is in $1, there for use strptime().
I understand you want the yrange ranging from 1 to 12 for the months of a year.
But where is the data you want to plot?
Maybe the following examples is a starting point to better find out what you really want.
Code:
### plotting dates...
reset session
$Data <<EOD
2019/01/01
2019/02/01
2019/03/01
2019/04/01
2019/05/01
2019/06/01
2019/07/01
2019/08/01
2019/09/01
2019/10/01
2019/11/01
2019/12/01
2020/01/01
2020/02/01
2020/03/01
2020/04/01
2020/05/01
2020/06/01
2020/07/01
2020/08/01
2020/09/01
2020/10/01
2020/11/01
2020/12/01
EOD
myTimeInputFmt = "%Y/%m/%d"
myTimeOutputXFmt = "%Y\n%m\n%d"
set xlabel "Date"
set format x myTimeOutputXFmt # to get enough space for the 3 lines of the label
set ylabel "Month"
set yrange [0.5:12.5]
set ytics 1
plot $Data u 0:(tm_mon(strptime(myTimeInputFmt,strcol(1)))+1): \
xtic(strftime(myTimeOutputXFmt,strptime(myTimeInputFmt,strcol(1)))) \
with points pt 7 lc "red" title 'data'
### end of code
Result:
Another way to read data properly
There is also the function 'timecolumn(N, "timeformat")' in gnuplot, although it can only be used in using. This is the function for reading the Nth column of input data as a datetime. The second argument of this function is optional if you use the format given by set timefmt. With it, your script will work by the following script.
#!/bin/gnuplot
set timefmt '%Y/%m/%d'
set xdata time
set format x '%m/%y'
set datafile separator ','
plot "data.csv" using 1:(tm_mon(timecolumn(1))) title 'data'
Why is tm_mon($1) constantly returning 0?
In your script, tm_mon($1) is interpreted as tm_mon("2019/01/01") when reading first line from 'data.csv'. tm_mon basically accepts the real value that represents an UNIX time as the argument. But, if a string value is given, tm_mon try to convert it into the real value and interpret as an UNIX time. So, tm_mon doesn't constantly returning 0. You would understand this behavior by trying the following commands.
gnuplot> print tm_mon(1607698800) ### 2020-12-12 in UNIX time
11.0
gnuplot> print tm_mon("1607698800")
11.0
gnuplot> print tm_mon("1607698800/05/06")
11.0

GNU plot on non uniform data in x axis with fix interval

9 1782.091513,
24 4731.999530,
36 6377.046661,
80 9377.983901,
108 9158.024005,
210 4314.926970,
540 56799.564,
2000 67908.2343,
7000 45345.657,
12000 34234.3624,
Plotting this giving me a graph on which i am not able to see the small values. I want to fix the interval b/w each value of x axis. So that graph will be visible on full table.
You can set your axes to be logarithmic:
set logscale x
set logscale y
Logscale is probably what you actually want here as pointed out by choroba. A second (less standard) way to plot this is to use the values in the first column as the xticlabels.
plot 'yourdatafile' u 2:xticlabels(1)
This will result in a plot where the values are equally spaced on the x-axis, labelled with the corresponding x positions from the datafile.

Plotting filled region between two dates in Gnuplot

On the x-axis, I have time as a date %Y-%m-%d. On the y axis I have integers.
Basically, I have a date range for each data point, usually given by a target date and a two week window on either side. I the plot the data point relative to that target window using vertical lines for the low and high ends of the window.
I would like to shade the region between the low and high end.
I tried adding " with filledcurves x1='2000-01-01'"
Thanks
I think you have a few options here. If there are only a few shaded regions that you want to draw, you can use a rectangle (I imagine that this will work -- though I haven't tested it):
set xdata time
set timefmt '%Y-%m-%d'
set object rectangle from first '2000-01-01',graph 0 to first '2001-01-14',graph 1 fc rgb "red" solid back
Another option is that you format your datafile like this:
#date value low-date high-date
2000-01-12 12 2000-01-01 2000-01-26
2000-02-12 12 2000-02-01 2000-02-26
2000-03-12 12 2000-03-01 2000-03-26
Note that there are two blank spaces between each "record" (triple spaced). If your file isn't triple spaced, you can do this easily (in gnuplot) using sed:
plot "< sed 'G;G' datafile.dat" ...
In the special case where low-date and high-date are exactly 3600*24*14 (number of seconds in two weeks) lower/higher than date, you can skip the last two columns and plot it like this:
NPOINTS=3 #Number of points in datafile.
YHIGH=15
set xdata time
set timefmt '%Y-%m-%d'
set style fill solid .5 noborder #somewhat transparent -- see "help fillstyle"
set yrange [0:YHIGH]
plot for [I=0:NPOINTS-1] 'test.dat' i I u 1:(YHIGH):(3600*24*14*2) w boxes,\
for [I=0:NPOINTS-1] 'test.dat' i I u 1:2 w points ls I+1
The first pass draws the rectangles, the second pass draws the points. This only works if the point is in the center of the range, and each range is exactly 3600*24*14 seconds (2 weeks). Note that you'll have to set the number of points and the YHIGH to some value which works for your data.
If the ranges can be skewed -- e.g. the range isn't centered on the point in question, you can probably do something like this:
NPOINTS=3
YHIGH=15
TIMEFMT='%Y-%m-%d'
set xdata time
set timefmt TIMEFMT
set style fill solid .5 noborder #somewhat transparent -- see "help fillstyle"
set yrange [0:YHIGH]
#difference between two times in seconds
boxwidth(s1,s2)=strptime(TIMEFMT,s1)-strptime(TIMEFMT,s2)
#average of two times -- number of seconds since 2000 epoch.
boxmidpoint(s1,s2)=(strptime(TIMEFMT,s1)+strptime(TIMEFMT,s2))/2
set macro #just to make it a little easier to read.
BOXARGS='stringcolumn(4),stringcolumn(3)'
plot for [I=0:NPOINTS-1] 'test.dat' i I u (boxmidpoint(#BOXARGS)):(YHIGH):(boxwidth(#BOXARGS)) w boxes,\
for [I=0:NPOINTS-1] 'test.dat' i I u 1:2 ls I+1

Plotting date/time data points and functions in the same graph

I want to plot a set of date/time data points with the x value specified by unix epoch, seconds since 1970. I also want to plot a trend function along with the data (yes I know gnuplot can do this for me, but this is an example). So I have data.txt that looks like this:
1303430400 67.5
1303862400 65.5
1304208000 62.9
1304553600 60.2
And I have a gnuplot program that looks like this:
set terminal png
set output 'plot.png'
set timefmt "%s"
set xdata time
plot "data.txt" using 1:2 title "Data points", \
-7.0/(1123200)*x + 8190.43 title "Trend"
Now, the function is simply a linear approximation of the data. I have checked the formula and it should be ok. For instance, plugging in 1304553600 (the last value of the range), you get 60.2.
I would expect to see my data points plotted along with the function roughly following the data points. Instead, the function plot is way off, about 6000 too high. Apparently I do not understand something about date/time plots. What should I do to get my expected result?
I found this in the man page: "[In date plots] gnuplot will also accept an integer expression, which will be interpreted as seconds from 1 January 2000."
There is a difference of 946684800 seconds between unix epoch and gnuplot time. This gnuplot script gives the expected plot (note the 946684800 addition to x):
set terminal png
set output 'plot.png'
set timefmt "%s"
set xdata time
plot "stackoverflow.txt" using 1:2 title "Data points", \
-7.0/(1123200)*(x+946684800) + 8190.43 title "Trend"

Resources