Home > OS >  ggplot2: Facetting by year and aligning x-axis dates by month
ggplot2: Facetting by year and aligning x-axis dates by month

Time:07-25

I am trying to plot daily data with days of the week (Monday:Sunday) on the y-axis, week of the year on the x-axis with monthly labels (January:December), and facet by year with each facet as its own row. I want the week of the year to align between the facets. I also want each tile to be square.

Here is a toy dataset to work with:

my_data <- tibble(Date = seq(
  as.Date("1/11/2013", "%d/%m/%Y"), 
  as.Date("31/12/2014", "%d/%m/%Y"), 
  "days"),
  Value = runif(length(VectorofDates)))

One solution I came up with is to use lubridate::week() to number the weeks and plot by week. This correctly aligns the x-axis between the facets. The problem is, I can't figure out how to label the x-axis with monthly labels.

my_data %>% 
  mutate(Week = week(Date)) %>% 
  mutate(Weekday = wday(Date, label = TRUE, week_start = 1)) %>% 
  mutate(Year = year(Date)) %>% 
ggplot(aes(fill = Value, x = Week, y = Weekday))  
  geom_tile()  
  theme_bw()  
  facet_grid(Year ~ .)  
  coord_fixed()

By week of year Alternatively, I tried plotting by the first day of the week using lubridate::floor_date and lubridate::round_date. In this solution, the x-axis is correctly labeled, but the weeks don't align between the two years. Also, the tiles aren't perfectly square, though I think this could be fixed by playing around with the coord_fixed ratio.

my_data %>% 
  mutate(Week = floor_date(Date, week_start = 1),
         Week = round_date(Week, "week", week_start = 1)) %>% 
  mutate(Weekday = wday(Date, label = TRUE, week_start = 1)) %>% 
  mutate(Year = year(Date)) %>% 
  ggplot(aes(fill = Value, x = Week, y = Weekday))  
  geom_tile()  
  theme_bw()  
  facet_grid(Year ~ .)  
  scale_x_datetime(name = NULL, labels = label_date("%b"))  
  coord_fixed(7e5)

By date of week Any suggestions of how to get the columns to align correctly by week of the year while labeling the months correctly?

CodePudding user response:

The concept is a little flawed, since the same week of the year is not guaranteed to fall in the same month. However, you can get a "close enough" solution by using the labels and breaks argument of scale_x_continuous. The idea here is to write a function which takes a number of weeks, adds 7 times this value as a number of days onto an arbitrary year's 1st January, then format it as month name only using strftime:

my_data %>% 
  mutate(Week = week(Date)) %>% 
  mutate(Weekday = wday(Date, label = TRUE, week_start = 1)) %>% 
  mutate(Year = year(Date)) %>% 
ggplot(aes(fill = Value, x = Week, y = Weekday))  
  geom_tile()  
  theme_bw()  
  facet_grid(Year ~ .)  
  coord_fixed()  
  scale_x_continuous(labels = function(x) {
    strftime(as.Date("2000-01-01")   7 * x, "%B")
  }, breaks = seq(1, 52, 4.2))

enter image description here

Another option if you're sick of reinventing the wheel is to use the calendarHeat function in the Github-only makeR package:

install_github("jbryer/makeR")
library(makeR)

calendarHeat(my_data$Date, my_data$Value)

enter image description here

  • Related