How to get a xtic for every month in Gnuplot?

Viewed 321

I am plotting a graph showing the maximum temperature every day during the last 12 months using:

set format x "1 %b"
set xrange[time(0)-3600*24*365:time(0)]

This gives a xtic for every month: 1 Jan, 1 Feb, 1 Mar ...

But if I try to extend the graph to the last 13 months, I get xtics only every second month: 1 Jan, 1 Mar, 1 May ...

set format x "1 %b"
set xrange[time(0)-3600*24*(365+31):time(0)]

How to get a xtic every month in this case?

3 Answers

In order to place the xtics at the first day of each month, try:

set format x "%d %b"
set xtics 60*60*24*30

and maybe

set mxtics 2 

to have an xtic in/near the middle of the month.

If you make a screenshot and count pixels or you take a ruler and measure the distance between the months on the screen, you will see that they are not equidistant but proportional to the length of the respective month.

As I understand, in your special case gnuplot's "autotic" places a tic only every second month. Now, if you want to force a tic every 1st of month you have the difficulty that the months do not have equal lengths, and you cannot simply set a fixed distance, e.g. like set xtics 3600*24*31.

Maybe there is a simple solution to this which I am not aware of. So, the idea for the following workaround is to set the tics "manually" in a loop. Basically, you loop through every day and create a string which contains only the tics for the 1st or the 15th of a month. Depending on your date input format you might have to do some adjustments. Check help xtics and help macros.

Update: as @maij mentions in the comments and in his answer, there is a simple(r) solution.

Code: (edit: now with input time format dd.mm.yyyy)

### force a tic every 1st and 15th of month
reset session
myTimeFmt = "%d.%m.%Y"

# create some random test data
set print $Data
do for [i=1:365+31] {
    print sprintf("%s %g",strftime(myTimeFmt,time(0)-i*3600*24),-i/360.+rand(0)+sin(i/36.))
}
set print

stats $Data u (timecolumn(1,myTimeFmt)) nooutput
DateStart = strptime(myTimeFmt,"01.".strftime("%m.%Y",STATS_min))  # the first day of the month
DateEnd   = STATS_max

myXtics = ''
do for [t=DateStart:DateEnd:24*3600] {
    myXtic = tm_mday(t)==1  ? sprintf('"%s" %.0f 0,',strftime("%b",t),t) : \
             tm_mday(t)==15 ? sprintf('""   %.0f 1,', t) : ''
    myXtics = myXtics.myXtic
}
set xtics (@myXtics)
set key top left

plot $Data u (timecolumn(1,myTimeFmt)):2 w l lc "red" ti "tics every 1st and 15th of the month"
### end of code

Result:

enter image description here

I think there's an easier way. Suppose you have time data on x spanning a known range.

 set xdata time
 set timefmt "%d.%m.%Y"        # Data in format dd.mm.yyyy
 set xrange ["01.01.2020" : "01.07.2021"]

Now we want to mark certain tics (1st day of month). We'll define tic labels for two full years, but only the in-range ones will actually be printed.

unset mxtics; unset ytics
set xtics (0)    # Clear out list of xtic labels
set for [mon=1:12] xtics add (strptime("%d.%m.%Y", sprintf("01.%02d.2020",mon)))
set for [mon=1:12] xtics add (strptime("%d.%m.%Y", sprintf("01.%02d.2021",mon)))

And finally you have the option to choose a different format for the actual tic labels

 set xtics time format "%b"           # Just the month name
 plot x

enter image description here

Related