highlight weekends using ggplot?

Using geom_area() is more concise, and will work for any date range.

    library(ggplot2)

    test <- data.frame(DATE=seq(from = as.POSIXct("2014-07-16 01:00"), 
                                to = as.POSIXct("2014-07-30 00:00"), 
                                by = "hour"),
                       count=floor(runif(336,1,100)))

    test$weekend <- weekdays(test$DATE) %in% c("Saturday", "Sunday")

    ggplot(data=test, aes(x=DATE, y=count)) +
      geom_area(aes(y=weekend*max(count)), fill="yellow") +
      geom_line() +
      labs(title="test")

enter image description here


Here's code that does both weekends in your data. You could generalize to any number of weekends by adding more geom_rect() calls (or calling a loop that does).

# your data
test <- data.frame(DATE=seq(from = as.POSIXct("2014-07-16 01:00"), to = as.POSIXct("2014-07-30 00:00"), by = "hour"),count=floor(runif(336,1,100)))
your_plot <- ggplot(test) + geom_line(aes(x=DATE,y=count)) + labs(title="test") 

# get all the start and end points
library(lubridate) # for hour function
sats <- which(hour(test$DATE)==0 & weekdays(test$DATE)=='Saturday')
suns <- which(hour(test$DATE)==23 & weekdays(test$DATE)=='Sunday')

# do your plot plus weekend highlights
your_plot +
  geom_rect(aes(xmin=DATE[sats[1]], xmax=DATE[suns[1]],
                  ymin=min(count), ymax=max(count)),
            fill='yellow', alpha=.005) +

  geom_rect(aes(xmin=DATE[sats[2]], xmax=DATE[suns[2]],
                ymin=min(count), ymax=max(count)),
            fill='yellow', alpha=.005)

Here's the output


Here is an approach using Tydiverse tools, and more precisely geom_tile. The advantage is that you have not to precise the x boundaries.

library(dplyr)
library(lubridate)
library(ggplot2)

test %>%
  # My preference :-)
  rename_all(tolower) %>%
  # Computing the weekends by converting in weekday starting on monday to ease the cut
  mutate(weekend = wday(date, week_start = getOption("lubridate.week.start", 1)) > 5) %>%
  ggplot() +
  geom_line(aes(x = date, y = count)) +
  # And here is the trick!
  scale_fill_manual(values = c("alpha", "yellow")) +
  geom_tile(aes(
    x = date,
    y = min(count),
    height = Inf,
    fill = weekend
  ), alpha = .4)

Result

Note: I've written a more detailed post on this topic.

Tags:

R

Ggplot2