Search code examples
rggplot2dplyrfacet-wrap

How to add a different x-intercept line to ggplot per facet group (R)


I have some data that resembles the following:

library(dplyr)
library(ggplot2)

dates <- c('2023-01-01','2023-01-02','2023-01-03','2023-01-04','2023-01-05','2023-01-06',
          '2023-01-07','2023-01-08','2023-01-09','2023-01-10','2023-01-11','2023-01-12',
          '2023-01-01','2023-01-02','2023-01-03','2023-01-04','2023-01-05','2023-01-06',
          '2023-01-07','2023-01-08','2023-01-09','2023-01-10','2023-01-11','2023-01-12',
          '2023-01-01','2023-01-02','2023-01-03','2023-01-04','2023-01-05','2023-01-06',
          '2023-01-07','2023-01-08','2023-01-09','2023-01-10','2023-01-11','2023-01-12')

values <- c(1,2,10,15,16,17,17,16,15,12,10,8,2,5,6,7,7,7,7,8,8,8,9,8,20,19,18,10,10,7,6,6,5,5,3,2)

grp1 <-rep('Group1',12)
grp2 <-rep('Group2',12)
grp3 <-rep('Group3',12)

groups <- c(grp1, grp2, grp3)

df <- cbind(dates, values, groups) |>
  as.data.frame() |>
  mutate(values = as.numeric(values),
         dates = as.Date(dates))

I want to plot values over time per group. So, I've constructed the following ggplot code:

ggplot(data = df, aes(x = dates, y = values, color = groups)) +
  geom_line() +geom_point() + 
  facet_wrap(~ groups, scales = 'free_y', ncol = 1)

However, I want to add a vertical x-intercept line that is different per facet group. Here is some extra code I've tried to meet this requirement:

cutoff_dates <- c('2023-01-02', '2023-01-04', '2023-01-06')

ggplot(data = df, aes(x = dates, y = values, color = groups)) +
  geom_line() +geom_point() + 
  facet_wrap(~ groups, scales = 'free_y', ncol = 1) +
  geom_vline(xintercept = as.Date(cutoff_dates), linetype = 'dashed')

However, this adds each of the cutoff values to each grouped plot. I want the first cutoff date to apply to the first group, 2nd cutoff to the second group, and so on. How should I modify my code to achieve this result?

Thank you!


Solution

  • You can add the cutoffs in a different dataframe and map it as an aesthetic inside aes() within geom_vline():

    cutoff_dates <- data.frame(
      cutoff = c('2023-01-02', '2023-01-04', '2023-01-06'),
      groups = c("Group1", "Group2", "Group3"))
    
    ggplot(data = df, aes(x = dates, y = values, color = groups)) +
      geom_line() +
      geom_point() + 
      facet_wrap(~ groups, scales = 'free_y', ncol = 1) +
      geom_vline(data = cutoff_dates,
                 mapping = aes(xintercept = as.Date(cutoff)), linetype = 'dashed')
    

    line chart