assuming I have data values like those:
8.31
8.25
8.13
8.06
8.00
7.94
7.88
and it is known that they were taken 30 seconds apart each, how can I plot them as minutes or hours in the x axis? I am just confused by not having a separate time column and hpoing gnuplot can do that without adding a new time column to the data file...
I currently use only:
plot 'data.log' u 0:1 with lines lw 2
which of cause give a dimensionless x axis...
Assuming the first point starts at time zero, you can just multiply the pseudo column with 30 to get seconds, e.g.:
plot 'data.log' using ($0 * 30):1 with lines linewidth 2
Output:
As mentioned by Dan in the comments, if you want minutes just divide by 60:
plot "data.log" using ($0 * 30 / 60):1 with lines linewidth 2
reset session
TimeInterval = 30
set xdata time
set format x "%tH:%tM"
plot 'data.log' u ($0*TimeInterval):1 with lines lw 2
Related
I have a file of data where the first column is time in seconds. The start of time is 0, and onward from there.
I want to plot the data with an x-axis formatted as days:hours:minutes:seconds. T=0 should map to 00:00:00:00. I can't figure out how to get days to start at 00 instead of 01. I have tried the below. I also tried setting xrange to [-86400:173000], but that maps to day 365, not 0. Shouldn't it be common to plot some time-sampled data, that may span days, starting with T=0?
It seems that GnuPlot needs a different set of time format characters for zero-based time plotting, instead of date-based. Unless it already has it and I have missed it.
data
0 0
3600 10
7200 30
21600 50
160000 100
GnuPlot script
set xdata time
set format x "%02j:%H:%M:%S"
set timefmt "%s"
set xrange [0:173000]
plot "data" using 1:2 with lines
I can get you part way there. Gnuplot has a separate set of time formats for relative time. Zero-based and handles positive and negative intervals. It's hard to find in the documentation, but here is a section from "help time_specifiers".
Format Explanation
%tH +/- hours relative to time=0 (does not wrap at 24)
%tM +/- minutes relative to time=0
%tS +/- seconds associated with previous tH or tM field
Examples of time format:
The date format specifiers encode a time in seconds as a clock time
on a particular day. So hours run only from 0-23, minutes from 0-59,
and negative values correspond to dates prior to the epoch
(1-Jan-1970). In order to report a time value in seconds as some
number of hours/minutes/seconds relative to a time 0, use time
formats %tH %tM %tS. To report a value of -3672.50 seconds
set format x # default date format "12/31/69 \n 22:58"
set format x "%tH:%tM:%tS" # "-01:01:12"
set format x "%.2tH hours" # "-1.02 hours"
set format x "%tM:%.2tS" # "-61:12.50"
Using these relative time formats with your sample data I can get as far as:
$data << EOD
0 0
3600 10
7200 30
21600 50
160000 100
EOD
set xtics time format "%tH:%tM:%tS"
set title 'set xtics time format "%tH:%tM:%tS"'
set xrange [0:173000]
plot $data using 1:2 with lp
Now the problem is that there is no equivalent relative day format. Call that a bug or at least a missing feature. Let's take a stab at adding days to the format by hand.
secperday = 3600*24
days(t) = gprintf("%02g:", int(t)/secperday)
hours(t) = strftime("%02tH:%tM:%tS", int(t)%secperday)
# Create ten days worth of tic labels
# Every six hours with no label; once a day with full label
set xtics 6*3600 format ""
do for [i=0:10] {
T = day * secperday
set xtics add ( days(T).hours(T) T )
}
plot $data using 1:2 with lp
As mentioned in the comments above, one workaround would be using week days, which however would limit you to 7 days.
Since 0 seconds correspond to Thursday, 01.01.1970 00:00:00 you have to subtract 4 days = 24*3600*4 seconds to make it a Sunday (=0).
Another strange workaround would be to use multiplot and plot twice, just for the day labels. You have to set a bottom margin to exactly "overplot" the previous plot. There would be still room for fine tuning.
By the way: If the scale is several days then the question is if seconds in the label are actually relevant?
Code:
### timedate days starting from zero
reset session
$Data <<EOD
0 0
3600 10
7200 30
21600 50
160000 100
450000 222
500000 333
EOD
set multiplot layout 2,1
# first workaround, limited to 7 days
set format x "day %1w\n%H:%M:%S" timedate
plot $Data u ($1-24*3600*4):2 w lp pt 7 notitle
# second workaround, using multiplot
set format x "\n%H:%M:%S" timedate
set bmargin 3
plot $Data u 1:2 w lp pt 7 notitle
set multiplot previous
set format x "day %s"
set xrange[GPVAL_X_MIN/86400:GPVAL_X_MAX/86400]
plot $Data u ($1/86400):2 w p ps 0 notitle # point size zero, i.e. invisible
unset multiplot
### end of code
Result:
$data << EOD
1563619139 10
1532083139 9
1500547139 8
1469011139 7
1437388739 6
1405852739 5
1374316739 4
1342780739 3
1311158339 2
1279622339 1
EOD
set terminal png
set xdata time
set timefmt "%s"
set format x '%Y'
unset key
plot '$data' u 1:2
How do I plot values only from say 2015? I tried plot ["2015":] '$data' u 1:2 via the docs but it doesn't work as expected.
I realise I could edit $data, but I don't want to do that.
There is an older an a newer gnuplot syntax for timedata.
The example below uses the newer syntax.
Check help time/date, help timecolumn, and help strptime.
Code:
### time data
reset session
$Data << EOD
1563619139 10
1532083139 9
1500547139 8
1469011139 7
1437388739 6
1405852739 5
1374316739 4
1342780739 3
1311158339 2
1279622339 1
EOD
unset key
set format x "%Y" time
StartTime = strptime("%Y","2015") # 2015-01-01 00:00:00 in seconds after 1970
set xrange[StartTime:]
set xtics StartTime, 3600*24*365 # start time and major tic distance one year in seconds
plot $Data u (timecolumn(1,"%s")):2 w lp pt 7
### end of code
Result:
You must use the same format of timefmt to specify the range.
plot ["1420092000":] '$data' u 1:2
The seconds in Gnuplot are measured starting from 1970.
I calculated the starting time considering 365.25 days in a year, hence 1420092000 s, but using strptime("%Y","2015"), as reported in the other answer, is without doubt more correct and precise.
You can add
set xtics 31557600
to have only major tics corresponding to the beginning of year. The value specified is the time increment between tics that must be given in seconds.
I am able to successfully reproduce Jitter examples from here: http://gnuplot.sourceforge.net/demo/violinplot.html
However, when I try to use my own data, the points are not "jittered".
Here is the data file (data.dat):
10 1 1 3 8 8 8
20 2 2 3 8 8 8
30 3 3 3 8 8 8
Here is a minimal gnuplot input file:
set jitter
plot 'data.dat' using 1:2 with points, '' u 1:3 with points, '' u 1:4 with points, '' u 1:5 with points, '' u 1:6 with points, '' u 1:7 with points
The points are right on top of each other, whereas I want points that are in the same place to be slightly offset (x-axis).
I've installed the latest version of gnuplot:
$ gnuplot --version
gnuplot 5.2 patchlevel 6
EDIT WITH SOLUTION:
#Ethan's comment cleared it up for me. I'm able to get the jittering by reorganizing my input data file so that it's a single dataset, which contains internal "collisions", rather than reading in lots of individual data sets. e.g:
10 1
10 1
10 3
10 3
20 2
20 2
30 8
30 8
And my gnuplot file is now just:
set jitter
plot 'data.dat' using 1:2 with points
"set jitter" will not work across multiple data sets as noted in the comment. You could do something similar by adding a random displacement in the 'using' specifier.
plot for [col=2:7] 'data.dat' using 1:(column(col) + (rand(0)-0.5)/2.) with points
This is different from "set jitter" because all points will be randomly displaced, whereas with jitter only overlapping points are shifted and the displacement is not random.
Alternatively, since in your case the columns are distinct perhaps you want to shift systematically based on the column number:
plot for [col=2:7] 'data.dat' using (column(1)+col/4.) : (column(col))
I have the below data in gnuplot:
2012-09-18 0 2 12
2012-03-15 1 4 5
2012-12-18 24 8 11
2012-09-18 2 8 11
2012-03-15 16 5 5
2011-12-06 5 2 3
2012-12-18 3 12 8
2012-09-18 4 4 8
2012-03-29 11 6 2
2011-12-06 9 7 3
2012-12-18 6 7 8
2012-09-18 4 3 8
2012-02-09 27 2 1
2012-12-18 2 1 8
2012-09-18 6 14 8
1st column; x (date)
2nd column; y
3rd column; the point color
4th column; number of occurrences(the point is duplicated)
I need to write a gnuplot program which:
Draws my (x,y) points.
Gives each point a different color depending on the 3rd column value (maybe over 50 different colors).
If the 4th column is greater than 0 then the point is duplicated and it must be drawn n times and give its x,y a random positing with a small margin. for example, (rand(x)-0.5,rand(y)-0.5).
Another question, what is the best and fastest way/tool to learn gnuplot?
This is supposed to be an extension to my answer for your other question drawing duplicated points in gnuplot with small margin:
You need to have the first column interpreted as time data. For this you need
set xdata time
set timefmt '%Y-%m-%d'
In order to set the point color, it is best to define a palette and then use linecolor palette, which sets the point color based on its value in the palette.
So, using the explanations from drawing duplicated points in gnuplot with small margin the final script is:
reset
filename = 'data.dat'
stats filename using 4 nooutput
set xdata time
set timefmt '%Y-%m-%d'
set format x '%Y-%m'
rand_x(x) = x + 60*60*24*7 * (rand(0) - 0.5)
rand_y(y) = y + (rand(0) - 0.5)
plot for [i=0:int(STATS_max)-1] filename \
using (rand_x(timecolumn(1))):(i < $4 ? rand_y($2) : 1/0):3 pointtype 7 linecolor palette notitle
Some other things you must have in mind are:
The stats call must come before set xdata time, because the statistics don't work with time data.
When calculating with time data in the using statement, one needs to use the timecolumn function (as opposed to column or $.. in generic cases). This gives the time as a timestamp (i.e. in seconds).
For that reason you need two different random functions for x and y, because of the very different scalings. Here, I used a 'jitter' of one week (60*60*24*7 seconds) on the time axis.
The result with 4.6.4 is:
Some remarks to your question about learning gnuplot: Try to solve your questions by yourself and then post more concrete questions! Browse through the gnuplot demos to see what is possible, look which feature or plotting style is used, look them up in the documentation, what options/settings are offered? Play around with those demos and try to apply that to your data sets etc. In the end its all about practice (I've been using gnuplot for 12 years...).
I'm trying to figure out how to do fence plots in gnuplot, but I'm having a hard time understanding what's going on in the examples I find on the internet.
I have a (varying) number of data sets from different points in time in my simulation, in a datafile organized as a matrix of values1:
t1 x11 y11 // indices here indicate that (x1,y1) are a data point which
t1 x21 y21 // I'd plot on a regular 2D plot for this timestep, with the
... // additional index noting which time step the values are for.
t1 xN1 yN1
[blank line]
t2 x12 y12
t2 x22 y22
...
t2 xN2 yN2
[etc...]
tM xNM yNM
I want to plot this with one fence for each time value. I can plot do simply splot 'data.txt' and get something which is quite similar to what I want - + markers along the "top edges" of the fences, with time on x axis, x-data on y axis and y-data on z axis. However, if I add something like w lines to the splot command I just get a surface with all the data series connected.
I've tried to adapt the examples from the demo script collection (about halfway down), but they both rely on a dummy variable, and I can't figure out how to combine that with my data series. I've found some other exampels as well, but they are all quite elaborate and I don't understand what they do at all.
What is a good way to create fence plots from data using gnuplot?
1 If it's necessary, it is possible to change this - I am in control of the code that generates the data. It's a hassle, though...
This does require a bit of a change to the data unfortunately. The change is pretty minor though and could probably be handled with a simple awk1,2 script:
Here's a copy/paste of my interactive gnuplot session:
gnuplot> !cat test.dat
1 2 3
1 2 0
1 3 4
1 3 0
1 4 5
1 4 0
2 2 3
2 2 0
2 3 4
2 3 0
2 4 5
2 4 0
3 2 3
3 2 0
3 3 4
3 3 0
3 4 5
3 4 0
!
gnuplot> splot 'test.dat' u 1:2:3 w lines
The thing to note here is that there are 2 blank lines between "fences" and each x,y data point appears twice with a blank line afterward. The second time it appears, the z-coordinate is 0.
To get each fence to have a different color:
gnuplot> splot for [i=0:3] 'test.dat' index i u 1:2:3 w lines
The awk script can even be done inline:
splot "< awk {...} datafile"
But that can get a little tricky with quoting (to include a single quote in a single quoted string, you double it) ...
AWKCMD='awk ''{if(!NF){print ""}else if(index($0,"#")!=1){printf "%s %s %s\n%s %s 0\n\n", $1,$2,$3,$1,$2}}'' '
splot '<'.AWKCMD.'datafile.dat' u 1:2:3 w lines
As far as efficiency is concerned, I'm believe that the iteration I used above will call the awk command for each time it iterates. The workaround here is to pull the color from the index number:
splot '<'.AWKCMD.' test.dat' u 1:2:3:(column(-2)) w l lc variable
I believe that this will only do the awk command once as desired so with only a million entries it should still respond relatively quickly.
1awk '{if(!NF){print ""}else{printf "%s %s %s\n%s %s 0\n\n", $1,$2,$3,$1,$2}}' test.dat
2awk '{if(!NF){print ""}else if(index($0,"#")!=1){printf "%s %s %s\n%s %s 0\n\n", $1,$2,$3,$1,$2}}' test.dat (version which ignores comments)