Search code examples
rggplot2plotlegendpatchwork

Patchwork won't assign common legend for combined plots


I have combined three plots using patchwork

enter image description here

I have followed this SO thread, where a similar issue was solved. However, applying that specific approach on my script does not solve the problem. I want one common legend for all three plots:

Expected output enter image description here

Script

library(ggplot2)
tti_type <- ggplot(p %>%
         bind_rows(., mutate(., type = "all")), 
       aes(x = type, y = logtti, color = corona, fill = corona)) + 
  geom_boxplot() + 
  scale_color_manual(name="", 
                     values = c("#8B3A62", "#6DBCC3"),
                     label = c("Before", "During lockdown")) + 
  scale_fill_manual(name = "",
                    values = c("#8B3A6220", "#6DBCC320"),
                    label = c("Before", "During lockdown")) +
  ggtitle("Time to treatment initiation") +
  theme(legend.position = "bottom")


los_type <- ggplot(p %>%
                     bind_rows(., mutate(., type = "all")), 
                   aes(x = type, y = loglos, color = corona, fill = corona)) + 
  geom_boxplot() + 
  scale_color_manual(name="", 
                     values = c("#8B3A62", "#6DBCC3"),
                     label = c("Before", "During lockdown")) + 
  scale_fill_manual(name = "",
                    values = c("#8B3A6220", "#6DBCC320"),
                    label = c("Before", "During lockdown")) +
  ggtitle("Length of stay") +
  theme(legend.position = "bottom")

los_afsnit <- ggplot(p %>%
         filter(!afsnit %in% c("ICU", "Other")) %>% droplevels() %>%
         bind_rows(., mutate(., afsnit = "all")), 
       aes(x = afsnit, y = loglos, color = corona, fill = corona)) + 
  geom_boxplot() + 
  scale_color_manual(name="", 
                     values = c("#8B3A62", "#6DBCC3"),
                     label = c("Before", "During lockdown")) + 
  scale_fill_manual(name = "",
                    values = c("#8B3A6220", "#6DBCC320"),
                    label = c("Before", "During lockdown")) +
  ggtitle("Per care unit") +
  theme(legend.position = "bottom")

Then, the following yields the first plot:

library(patchwork)
(los_type / los_afsnit) | tti_type

First attempt still yields the first plot

(los_type / los_afsnit) | tti_type +
  plot_layout(guides = "collect") & theme(legend.position = 'bottom')

Second attempt still yields the first plot

(los_type / los_afsnit) | tti_type +
  plot_annotation(theme = theme(legend.position =  "bottom"))

Data sample

p <- structure(list(type = c("Vascular", "Traume", "Other", "Vascular", 
"Vascular", "Other", "CSF", "Other", "Vascular", "Vascular", 
"Other", "CSF", "Traume", "Tumor", "Vascular", "Vascular", "Vascular", 
"Vascular", "Vascular", "Tumor", "CSF", "Other", "CSF", "Other", 
"Vascular", "CSF", "CSF", "Traume", "Other", "CSF", "Vascular", 
"Vascular", "Tumor", "CSF", "Vascular", "Other", "Tumor", "CSF", 
"Vascular", "Traume", "Vascular", "Vascular", "Vascular", "Vascular", 
"Tumor", "Vascular", "Other", "Tumor", "Vascular", "CSF"), corona = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L), .Label = c("Normal", "C19"), class = "factor"), loglos = c(2.874, 
1.922, 1.536, 4.236, 1.036, -2.12, -0.667, 1.561, 2.409, 4.091, 
2.824, 4.368, 0.934, 1.007, 3.97, 4.438, 3, 3.802, -3.322, 1.967, 
-1.556, 1.47, 1.628, 2.284, 3.771, 4.099, 1.293, 2.531, 3.219, 
3.903, 3.621, 0.379, 2.208, 2.787, 1.911, 1.151, 2.57, 1.872, 
3.282, -0.029, 0.632, 1.367, 3.467, 2.186, 2.478, 1.922, 2.029, 
2.446, 3.257, 1.111), logtti = c(1.963, 1.485, 3.018, 0.926, 
2.233, 4.336, 3.154, 4.828, 0.926, 4.655, 6.14, -0.322, 1.485, 
5.409, 3.678, 4.027, 1.138, 4.322, 0, 5.776, 6.446, 4.672, 2.293, 
5.53, 0.926, 2.406, 4.954, 1.585, 2.293, 5.794, 2.17, 1.263, 
0.485, 0.678, 1.433, 6.34, 6.127, 1.678, 4.217, 2.807, 3.973, 
1.585, 2.744, 0.848, -0.737, 4.121, 6.567, 6.252, 3.722, 4.466
), afsnit = c("NIMA", "NK", "NK", "NIMA", "NIMA", "NIA", "NIA", 
"NK", "NK", "NIMA", "NK", "NK", "NIA", "NK", "NK", "NK", "NIA", 
"NIMA", "NIA", "NK", "NK", "NK", "NIA", "NIA", "NIMA", "NK", 
"NK", "NIMA", "NIMA", "NIMA", "NIA", "NIA", "NIA", "NIA", "NIMA", 
"NK", "NK", "NK", "NIMA", "NIA", "NIA", "NIA", "NK", "NIMA", 
"NIA", "NIA", "NK", "NK", "NIMA", "NK")), class = "data.frame", row.names = c(NA, 
-50L))

Solution

  • You have to enclose the gg objects into brackets so the plot_layout will work on the combined plot rather than tti_type only:

    ((los_type / los_afsnit) | tti_type) +
      plot_layout(guides = "collect") & theme(legend.position = 'bottom')