I'd like to plot hours of the day on the x axis, but print the date when the day rolls over from one day to the next. So the x axis might look like this:
11/02 04:00 08:00 12:00 16:00 20:00 11/03 04:00 08:00 ...
Is there a sane way to do this in gnuplot?
FWIW, my file currently looks something like this:
set xdata time
set timefmt "%Y-%m-%d|%H:%M:%S"
plot '-' using 1:2 with lines linewidth 1 linecolor rgb "#FF0000"
2013-11-02|00:00:48 123.0
2013-11-02|00:00:55 124.0
2013-11-02|00:01:06 121.0
2013-11-02:00:01:17 123.0
...
2013-11-04|23:59:41 241.0
2013-11-04|23:59:52 241.0
That is a tough one, made me think a bit. Here is how you can do it:
You need to set the format of the x-axis to %H:%M and then replace the 00:00 with dates, similarly like done in this answer.
The main work is then to extract the timestamps for the mid nights. I use the stats command for this (needs at least version 4.6.0), but because it doesn't support time data you must fiddle around a bit with strptime and similar:
fmt = "%Y-%m-%d|%H:%M:%S"
stats 'file.txt' using (strptime(fmt, stringcolumn(1))) nooutput
t = int(STATS_min)
t_start = t - tm_hour(t)*60*60 - tm_min(t)*60 - tm_sec(t)
num_days = 2 + (int(STATS_max) - t)/(24*60*60)
set xdata time
set timefmt fmt
set xtics 4*60*60
set for [i=1:num_days] xtics add (strftime('%m/%d', t_start+(i-1)*24*60*60) t_start+(i-1)*24*60*60)
set format x '%H:%M'
plot 'file.txt' using 1:2 with lines
I increment num_days by 2 to account for the possible automatic extension of the x-range to the next tics.
The result with your data is (with 4.6.4):
Here is a version with xticlabels:
$data <<EOD
2013-11-02|00:00:48 123.0
2013-11-02|00:00:55 124.0
2013-11-02|00:01:06 121.0
2013-11-02|00:01:17 123.0
2013-11-04|23:59:41 241.0
2013-11-04|23:59:52 241.0
EOD
set xdata time
set timefmt "%Y-%m-%d|%H:%M:%S"
plot $data using 1:2 w l # plot to get GPVAL_X_MIN GPVAL_X_MAX
t = GPVAL_X_MIN
t_start = t - tm_hour(t)*60*60 - tm_min(t)*60 - tm_sec(t)
num_days = 1 + (GPVAL_X_MAX-GPVAL_X_MIN)/(24*60*60)
replot [i=0:6*num_days:1] '+' us (t=t_start+i*24*60*60/6, strftime('%Y-%m-%d|%H:%M:%S', t)):(NaN):xtic(strftime(int(i)%6?'%H:%M':'%m-%d',t)) t ""
So the format is selected with int(i)%6?'%H:%M':'%m-%d'.
This was inspired by gnuplot: set link and x2tics in interactive mode.
Related
I'm trying to follow the guide to plotting financial data on gnuplot found here:
http://gnuplot.sourceforge.net/demo/finance.html
I generated some data and tried plotting with the following script:
1 set datafile separator ","
2 set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"#cccccc" behind
3
4 set xdata time
5 set timefmt "%Y-%M-%dT%H:%M:%S"
6 set format x "%d-%H"
7
8 set ylabel "Price"
9 set xlabel 'Time'
10
11 set style line 100 lt 1 lc rgb "grey" lw 0.5
12 set style line 101 lt 1 lc rgb "orange" lw 1
13
14 set grid ls 100
15 set key off
16
17 plot "lastrun.dat" using 1:2 with lines, '' using 1:3 with lines ls 101, '' using 1:4 with lines ls 101
however the resulting graph seems to not stich together the data correctly, so instead of one chart, i have three in the same space.
i'm sure i'm making a simple error but I've been stumped about what that is.
Check help time_specifiers:
%d day of the month, 01–31
%H hour, 00–23 (always two digits)
%m month, 01–12
%M minute, 0–60
%S second, integer 0–60 on output, (double) on input
%Y year, 4-digit
I have to "reinvent" a diagram like the following:
My problem is, the "filledcurves" option does not work correctly, if I use the different scaled y-axis.
set y2tics textcolor rgb "black"
set ytics nomirror
set yrange [0:80]
set y2range [0:180]
set key off
set grid dashtype 5 # auch dt ".-." möglich
plot "klima_flach.txt" using 1:3:4 with filledcurves x1,\
"" using 1:4 with lines axis x1y2,\
"" using 1:3:xtic(2) with lines axis x1y1
The used data is the following:
0 0 11 50
1 J 10 70
2 F 11 42
3 M 12 50
4 A 15 50
5 M 18 20
6 J 22 10
7 J 25 1
8 A 25 20
9 S 23 40
10 O 20 80
11 N 25 70
12 D 11 60
Any ideas, how I can get this problem solved?
By the way: A pattern as in the original diagram... possible or not?
#Wolfgang Höfer, the scaling between the axes in such type of Walter/Lieth-climate diagrams is 2. Hence, your y-range should be [0:90] and hence scaling factor 90./180.
Nevertheless, I assume #Christoph's answer solved your problem.
To your last question: a pattern as in your picture, i.e. a vertical hatch pattern? That's what I asked here (Hatch patterns in gnuplot) recently. Apparently, it's seems not possible in gnuplot.
Some time ago, I also "struggled" with climate diagrams, i.e. with filledcurves and even nonlinear axes. I would like to provide the code which I ended up. Maybe it will be useful to you or to others to draw such climate diagrams with gnuplot. If you are reading from a file, replace $DataIn with your filename. Suggestions and improvements are welcome.
# Walter/Lieth climate diagram with nonlinear axis
reset session
set encoding "utf8"
$DataIn <<EOD
# Mumbai/India, 18°54'N/72°49'E, 11 m
# No. Month Temperature Precipitation
1 January 23.9 3
2 February 23.9 3
3 March 26.1 3
4 April 28.1 2
5 May 29.7 18
6 June 28.9 485
7 July 27.2 617
8 August 27.0 340
9 September 27.0 264
10 October 28.1 64
11 November 27.2 13
12 December 25.6 3
EOD
# in order to be flexible for different input files
ColTemp = 3 # col# temperature
ColPrec = 4 # col# precipitation
# get location label from first commented row starting after '# '
set datafile commentschar "" # set the comment char to none
set datafile separator "\n" # data will be a full line
set table $Dummy # plot following data to a dummy table
# plots only first line 'every ::0::0' as string to the dummy table
# and assigns this line starting after the 3rd character to variable 'Location'
plot $DataIn u (Location = stringcolumn(1)[3:]) every ::0::0 with table
unset table # stop plotting to table
set datafile commentschar "#" # restore default commentschar
set datafile separator whitespace # restore default separator
set label 1 at graph 0.02,0.96 Location font ",10" # put label on graph
# set periodic boundaries, i.e. add lines of Dec and Jan again
# independent of the input format $DataIn, column1 of $Data will be the number of month
set datafile separator "\n"
set table $Data
plot $DataIn u (0):(stringcolumn(1)) every ::11::11 with table
plot $DataIn u ($0+1):(stringcolumn(1)) with table
plot $DataIn u (13):(stringcolumn(1)) every ::0::0 with table
unset table
set datafile separator whitespace
# print $Data
# settings for nonlinear scale
ScaleChangeAt = 100.
ScaleChangeFactor = 5.
f1(y) = (y<=ScaleChangeAt) ? y : ((y - ScaleChangeAt)/ScaleChangeFactor + ScaleChangeAt)
f2(y) = (y<=ScaleChangeAt) ? y : ((y - ScaleChangeAt)*ScaleChangeFactor + ScaleChangeAt)
f3(y) = f1(y)/2. # relation between axes y and y2; standard for Walter/Lieth climate diagrams
set nonlinear y2 via f1(y) inverse f2(y)
# settings for x-axis
set xrange[0.5:12.5]
set xtics 1 scale 0,1
set mxtics 2
set grid mxtics
# create months labels from local settings
do for [i=1:12] {
set xtics add (strftime("%b",strptime("%m",sprintf("%g",i))) i)
}
# settings for y- and y2-axes
stats [*:*] $DataIn u ColTemp:ColPrec nooutput
Round(m,n) = int(m/n)*n + sgn(m)*n
Ymin = STATS_min_x > 0 ? 0 : Round(STATS_min_x,10)
Ymax = 50
Y2min = Ymin < 0 ? f1(Ymin)*2 : 0
Y2max = Round(STATS_max_y,10**int(log(STATS_max_y)/log(10))) # round to next 10 or 100
# print Ymin, Ymax, Y2min, Y2max
# y-axis
set ylabel "Temperature / °C" tc rgb "red"
set yrange [Ymin:f3(Y2max)] # h(Y2max)]
set ytics 10 nomirror tc rgb "red"
# "manual" setting of ytics, up to 50°C
set ytics ("0" 0)
do for [i=Ymin:50:10] {
set ytics add (sprintf("%g",i) i)
}
# settings for y2-axis
set y2label "Precipitation / mm" tc rgb "blue"
set y2range [Y2min:Y2max]
# "manual" setting of y2tics
set y2tics nomirror tc rgb "blue"
set y2tics ("0" 0)
set grid y2tics
do for [i=20:ScaleChangeAt:20] {
set y2tics add (sprintf("%g",i) i)
}
do for [i=ScaleChangeAt:Y2max:20*ScaleChangeFactor] {
set y2tics add (sprintf("%g",i) i)
}
plot \
$Data u 1:ColTemp+1:(f3(column(ColPrec+1))) axis x1y1 w filledcurves above lc rgb "yellow" not,\
'' u 1:ColTemp+1:(f3(column(ColPrec+1))) axis x1y1 w filledcurves below fs pattern 4 fc rgb "blue" not,\
'' u 1:(f3(ScaleChangeAt)):(f3(column(ColPrec+1))) axis x1y1 w filledcurves below fs solid 1.0 fc rgb "blue" not,\
'' u 1:ColTemp+1 w l lw 2 lc rgb "red" not,\
'' u 1:ColPrec+1 axes x1y2 w l lw 2 lc rgb "blue" not
### end of code
which results in:
The filledcurves doesn't have an option for choosing different axes for the y-values in column two and three. But you are in the lucky situation, that you have fixed y-ranges. So you can define a scaling function for one of the columns:
set y2tics textcolor rgb "black"
set ytics nomirror
set yrange [0:80]
set y2range [0:180]
scale = 80.0/180.0
set key off
set grid dashtype 5 # auch dt ".-." möglich
plot "klima_flach.txt" using 1:3:(scale*$4) with filledcurves,\
"" using 1:4 with lines axis x1y2,\
"" using 1:3:xtic(2) with lines axis x1y1
With this datafile (x.txt)
20180522110000 6.03
20180522144500 10.44
20180523071501 5.17
and this command file (x.gnuplot)
set term png
set output "x.png"
set xdata time
set timefmt "%Y%m%d%H%M%S"
set format x "%H:%M"
plot "x.txt" using :2 w lines
and using gnuplot 5.0
I don't get the desired x-labels. I get only
00:00 00:00 00:00 00:00
not (something more like, give or take some details...)
11:00 .... 07:15
What am I doing wrong?
Solved it.
I was missing "1"
Wrong:
plot "x.txt" using :2 w lines
Correct:
plot "x.txt" using 1:2 w lines
This command draws nice green sine waves from a data file, but the col4 value goes negative periodically.
"" u (myDateSP(1,2)):4 lc rgb "green" lt 1 lw 6 sm cspl notitle,\
I'd like to have it draw the line red for negative values of col4 and green for positive values and it seems as if I should be able to use the ternary operator for that but I'm having problems with the grammar:
"" u (myDateSP(1,2)):4:($4<= 0) ? lc rgb "red" lt 1 lw 6 sm cspl notitle,\:lc rgb "green" lt 1 lw 6 sm cspl notitle,\
and other variants throw errors. Can someone point out where I have this wrong?
Your table example works nicely, many thanks.
I tried to apply it to a data file like this:
2015-01-03 18:02 01 29.49 feet High Tide
2015-01-04 01:12 01 -2.29 feet Low Tide
2015-01-04 07:02 01 29.09 feet High Tide
2015-01-04 13:22 01 4.54 feet Low Tide
2015-01-04 18:41 01 29.80 feet High Tide
2015-01-04 19:54 01 Full Moon
2015-01-05 01:52 01 -1.87 feet Low Tide
2015-01-05 07:36 01 29.30 feet High Tide
2015-01-05 14:00 01 4.51 feet Low Tide
2015-01-05 19:17 01 29.99 feet High Tide
2015-01-06 02:26 01 -1.30 feet Low Tide
and am not having much luck.
Using this:
set linetype 11 linecolor rgb "green"
set linetype 12 linecolor rgb "red"
set xdata time
set timefmt '%Y-%m-%d'
set format x '%s'
set table 'data-smoothed1.txt'
set samples 1000
plot 'data.txt' using 1:4 smooth cspline
unset table
set timefmt '%s'
set format x '%Y-%m-%d'
set xzeroaxis
plot 'data-smoothed.txt' using 1:4:($4 < 0 ? 12 : 11) linecolor variable with lines no title
It complains that the xrange is wrong, so when I add an range with the beginning and ending dates, it still doesn't help. The "01" column is the month number.
You must use linecolor variable, which allows you to give an additional column which specifies the linecolor to use. But that doesn't work directly with smooth, so that you must first write the smoothed data to an external file (with gnuplot 5 you can also use a heredoc) and then plot this file with linecolor variable.
When doing this, you must also take care of which time format is used to write the smoothed data. The format is taken from the set format x settings. I would use %s, i.e. Unix timestamp.
Here is a full, self-contained example showing the different steps:
An example file data.txt:
2014-02-11 2
2014-03-12 -1
2014-04-15 3
2014-05-22 -2
And the script
set linetype 11 linecolor rgb "green"
set linetype 12 linecolor rgb "red"
set xdata time
set timefmt '%Y-%m-%d'
set format x '%s'
set table 'data-smoothed.txt'
set samples 1000
plot 'data.txt' using 1:2 smooth cspline
unset table
set timefmt '%s'
set format x '%Y-%m-%d'
set xzeroaxis
plot 'data-smoothed.txt' using 1:2:($2 < 0 ? 12 : 11) linecolor variable with lines notitle
I'm trying to plot a histogram with the xtics as time information. The gp script I'm using is this one:
set style data histogram
set style histogram cluster gap 1
set boxwidth 1
set datafile separator "\t"
set yrange[0:3000]
set xlabel "xaxis"
set ylabel "yaxis"
set xdata time
set timefmt "%Y-%m-%d %H"
set terminal png size 1200,800
set output outputfile
plot inputfile u 2:1 title "Count"
An example of my inputfile(that I pass by parameter) is this one:
2012-07-22 00:00:00 159.361111111
2012-07-22 01:00:00 207.019166667
2012-07-22 02:00:00 191.749722222
2012-07-22 03:00:00 147.647777778
2012-07-22 04:00:00 107.751388889
2012-07-22 05:00:00 95.9566666667
2012-07-22 06:00:00 110.405277778
2012-07-22 07:00:00 151.689166667
2012-07-22 08:00:00 244.787777778
2012-07-22 09:00:00 481.601388889
However I'm receiving the error "plot_timeflow.gp", line 16: Too many columns in using specification and when I try to set the plot command to plot inputfile u 2:xticlabels(1) title "Count" I have the following error: "plot_timeflow.gp", line 16: Need full using spec for x time data.
Does someone have any ideia, what is the problem??
Thanks in advance.
Strange indeed. But in any case, for your data the boxes plotting style is better, because with histograms, every box has an own xtic. With boxes, the x-axis is treated as a normal time axis:
set boxwidth 0.8 relative
set datafile separator "\t"
set yrange[0:3000]
set xlabel "xaxis"
set ylabel "yaxis"
set xdata time
set timefmt "%Y-%m-%d %H"
set style fill solid
plot 'data.txt' using 1:2 with boxes title "Count"
That gives: