Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply holiday labels to plot by week of year

Tags:

r

ggplot2

I have some holiday dates, and a bunch of data by week of year. I'm plotting the data and want to make the X axis labels only show up when there is a holiday from my holidays table. The rest of the labels should be hidden. I think what I need is a list where the names are the weeks of year and the values are the strings I want, but I can't figure out how to generate that programatically.

library(tidyverse)
library(lubridate)

holiday_dates = c(
  "2016-01-01",
  '2016-01-18',
  '2016-02-15',
  '2016-05-08',
  '2016-05-30',
  '2016-06-19',
  '2016-07-04',
  '2016-09-16',
  '2016-10-10',
  '2016-11-11',
  '2016-11-24',
  '2016-12-25'
)
holiday_names = c(
  'New Years Day',
  'Martin Luther King Day',
  'Presidents Day',
  'Mothers Day',
  'Memorial Day',
  'Fathers Day',
  'Independence Day',
  'Labor Day',
  'Columbus Day',
  'Veterans Day',
  'Thanksgiving',
  'Christmas Day'
)
holidays = data.frame(Date = as.Date(holiday_dates), Holiday = holiday_names) %>%
  mutate(WeekOfYear = week(Date))

# can't figure out how to make this a list with names generates from the WeekOfYear column
holiday_labels = data.frame(WeekOfYear = seq(1,52)) %>% 
  left_join(holidays) %>% 
  .$Holiday

my_data %>%
  ggplot(aes(x=WeekOfYear, y=Gross, group=WeekOfYear)) +
  geom_line() +
  scale_x_discrete(
    names = holiday_labels,
    na.value = ""
  )
like image 399
Nick Larsen Avatar asked Oct 08 '16 20:10

Nick Larsen


1 Answers

  • Use scale_x_continuous rather than scale_x_discrete
  • Set both labels and breaks, with the corresponding text labels and the dates where you want them. In particular, for breaks use week(as.Date(holiday_dates)) to put it on the same scale as your data.

For example:

data_frame(WeekOfYear = 1:52, Gross = rnorm(52)) %>%
  ggplot(aes(x = WeekOfYear, y = Gross)) +
  geom_line() +
  scale_x_continuous(
    labels = holiday_names,
    breaks = week(as.Date(holiday_dates))
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

Note that I also rotated the x-axis labels to make it readable.

like image 91
David Robinson Avatar answered Oct 16 '22 16:10

David Robinson