0

I have a plot with dates on X axis and I want to add shading to distinguish weekends and holidays. I figured I can do it using POSIXct. I define a function to figure out if a day is a weekend:

weekend<-function(data) {
  d<-weekdays(data)
  ifelse (d %in% c("niedziela","sobota", "Sunday", "Sun", "Saturday", "Sat"), "weekend", "working")
}

Then I define my datasets - the actual dataset ad a table of weekends:

dates=as.character(seq(as.Date("2018-10-24"), as.Date("2018-11-01"), "day"))
numbers=rnorm(length(dates))

tabela=data.table(dates=as.POSIXct(dates), numbers=numbers)
tabela[,day_type:=weekend(dates)]

tab_weekend<-tabela[day_type=='weekend']
tab_weekend[,Start:=dates-12*60*60+1]
tab_weekend[,Stop:=dates+12*60*60]

Then I plot the numbers as a line and the weekends as gray rectangles.

g<-ggplot(tabela)+
  geom_line(aes(dates, numbers))+
  geom_rect(data=tab_weekend, aes(xmin=Start, xmax=Stop, ymin=-Inf, ymax=+Inf), 
            fill='gray65', alpha=0.2)+
  scale_x_datetime(labels=function(x) format(x, "%Y-%m-%d %H:%M"))

So far so good:

enter image description here

But if I now use a bigger range of dates,

dates=as.character(seq(as.Date("2018-10-01"), as.Date("2018-11-01"), "day"))

I get ticks every week which is not a problem in itself, but now the last tick shows the wrong date. Under the point of 29.10. (Monday) it says 28.10. 23:00.

enter image description here

I am guessing this happends because 28.10. is the first day of winter time, so it has 25 hours. But how do I fix it to have correct dates shown?

EDIT: it was suggested to use date_format with tz argument as in R: as.POSIXct timezone and scale_x_datetime issues in my dataset . However, with

scale_x_datetime(labels=date_format("%Y-%m-%d", tz = "Europe/Berlin"))

I still see ticks for 10-15, 10-22 and then 10-28.

MonikaP
  • 147
  • 9
  • 2
    Possible duplicate of [R: as.POSIXct timezone and scale\_x\_datetime issues in my dataset](https://stackoverflow.com/questions/36227130/r-as-posixct-timezone-and-scale-x-datetime-issues-in-my-dataset) – hdkrgr Dec 11 '18 at 15:19
  • The gist of answer linked above: R knows 'actual' time zones, like UTC etc., and 'geographical' ones, like e.g. 'Europe/Berlin'. Choosing the latter type will do the conversion for you (i.e. display 'CET' during winter and 'CEST' during summer.) – hdkrgr Dec 11 '18 at 15:22
  • I ran your code and cannot reproduce the `23:00` portion, it might be OS-specific or something else. (I'm on win10, R-3.5.1.) – r2evans Dec 11 '18 at 15:25
  • 1
    @r2evans: I suspect it will depend on your local timezone. – hdkrgr Dec 11 '18 at 15:37
  • @hdkrgr the question you linked deals with situation when data and axis are in different timezones and thus shifted. In my case, the shift happens on the daylight saving weekend, and only in some cases - the first plot is rendered correctly. – MonikaP Dec 11 '18 at 15:48
  • @r2evans I have LC_TIME=Polish_Poland.1250 if that helps. – MonikaP Dec 11 '18 at 15:48

1 Answers1

1

I think you're right it's a timezone issue, I can reproduce here in the Netherlands (CET, or CEST in summer).

But solving it is I think easier if you stop thinking in date-times altogether. It depends on your real data, but it looks like you have daily data, and times have no real meaning anyway.
Which you can also see in your example: all numbers are plotted at the start of the day, at midnight. That makes sense if you're plotting some measurement that's always taken at midnight, but not if you plot something that covers the whole day.
Also, as plotted right now you define the weekend kind of weird: it starts at Friday noon, and ends at Sunday noon.

So just using dates probably makes more sense, when I change your code I get this (I've also changed the conversion of dates to characters, it's unnecessary):

 dates=seq(as.Date("2018-10-24"), as.Date("2018-11-01"), "day")
 numbers=rnorm(length(dates))

 tabela=data.table(dates=dates, numbers=numbers)
 tabela[,day_type:=weekend(dates)]

 tab_weekend<-tabela[day_type=='weekend']
 tab_weekend[,Start:=dates-.5]
 tab_weekend[,Stop:=dates+.5]

 print(g<-ggplot(tabela)+
         geom_line(aes(dates, numbers))+
         geom_rect(data=tab_weekend, aes(xmin=Start, xmax=Stop, ymin=-Inf, ymax=+Inf), 
                   fill='gray65', alpha=0.2)+
         scale_x_date(labels=function(x) format(x, "%Y-%m-%d")))
Emil Bode
  • 1,784
  • 8
  • 16
  • yes, this works for my case, I only used the time for defining weekends. Actually at first I did try it with Date, but I couldn't get the syntax right. – MonikaP Dec 11 '18 at 15:59
  • just to clarify, I only showed the hour on the axis so that it's clear what's happening. In the actual plot I was showing only the dates, so the midnight/noon weirdness was not visible – MonikaP Dec 11 '18 at 16:07