2

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.

2 Answers 2

2

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

2

Using ggarrange:

common.legend: If TRUE, a common unique legend will be created for arranged plots.

library(tidyverse)
library(ggpubr)

plot_histogram <- function() {
  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()
}

plot_scatter <- function() {
  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()
}

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

ggarrange(
  scatter_plot_left, scatter_plot_middle,  
    scatter_plot_right, histogram_plot, 
  common.legend = TRUE, legend = "bottom", nrow = 1
)

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

3
  • This is a valid solution, but only if we have an odd number of graphs. How do I center it if it's an even number of graph? I should have made this clear.
    – NoNameBoyy
    Commented May 3 at 17:26
  • Nice idea, but note that even for odd number of plots due to the unequal widths, the legend is not entirely centered. Cheers.
    – M--
    Commented May 3 at 21:17
  • 1
    Yes, updated with ggarrange which looks okay with 4 plots.
    – Carl
    Commented May 3 at 22:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.