Search code examples
rggplot2legendpatchwork

Specify which legend to keep in wrap_plots


I'm looking to combine multiple graphs generated from different functions into a single display. Specifically, I want to only keep the legend of the first graph in the wrap.

Here is a minimal version of the problem:

library(ggplot2)
library(patchwork)

plot_histogram <- function() {
    plot_data <- ggplot(mtcars, aes(x = mpg, fill = factor(am))) +
        geom_histogram(binwidth = 2, color = "black") +
        labs(title = "Histo",
             x = "Miles/gallon",
             y = "nb cars",
             fill = "Transmission") +
        scale_fill_manual(values = c("skyblue", "salmon"), 
                          labels = c("Auto", "Man")) +
        theme_minimal() +
        theme(legend.position = "bottom")
    
    return(plot_data)
}

plot_scatter <- function() {
    plot_data <- ggplot(mtcars, aes(x = mpg, y = wt, color = factor(cyl))) +
        geom_point(size = 3) +
        labs(title = "Scatterplot",
             x = "Miles/gallon",
             y = "weight",
             color = "Cyl") +
        theme_minimal() +
        theme(legend.position = "bottom")
    
    return(plot_data)
}

scatter_plot_left <- plot_scatter()
scatter_plot_right <- plot_scatter()
histogram_plot <- plot_histogram()

combined_plots <- wrap_plots(scatter_plot_left + scatter_plot_right,
                             histogram_plot,
                             nrow = 1,
                             widths = c(3, 1)) +
    plot_layout(guides = 'collect') &
    theme(legend.position = "bottom")

combined_plots

Is there a way to preserve only the legend of the scatter plot?

From now, the best "solution" I've found is to wrap the first two graphs with guides = 'collect', and the wrap it with the other graph without keeping the legend.

This isn't really a solution, since the legend isn't centered and you have to adjust the size of the graphics each time, which isn't good in an automatic production process.


Solution

  • We can use layout design, which can work for both odd and even number of plots:

    scatter_plot_left <- plot_scatter()
    scatter_plot_middle <- plot_scatter()
    scatter_plot_right <- plot_scatter()
    histogram_plot <- plot_histogram() + theme(legend.position = "none") 
    
    custom_lyt <- "AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   AAABBBCCCDD
                   ####ZZZ####"
    
    scatter_plot_left + scatter_plot_middle + scatter_plot_right + 
        histogram_plot + 
        guide_area() +
      plot_layout(guides = 'collect', design = custom_lyt)
    

    custom_lyt <- "AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   AAACCCDD
                   ###ZZ###"
    
    scatter_plot_left + scatter_plot_right + 
        histogram_plot + 
        guide_area() +
      plot_layout(guides = 'collect', design = custom_lyt)
    

    Created on 2024-05-03 with reprex v2.0.2