patchwork icon indicating copy to clipboard operation
patchwork copied to clipboard

Collecting guides from list of plots with partially matching legends

Open almita opened this issue 1 year ago • 3 comments

Here's an example:

set.seed(10)
library(dplyr)
library(purrr)
library(ggplot2)
library(patchwork)
data <- list()
for(i in 1:4){
    x <- rnorm(4)
    y <- rnorm(4)
    z <- sample(x = c("B1", "B2", "B3", "B4"), replace = TRUE)
    data[[i]] <- data.frame(x,y,z)
}

pal <- c("B1"="red", "B2"="blue", "B3"="green", "B4"="black")

names(data) <- c("A1", "A2", "A3", "A4")

plots <- map(data, ~ .x %>% ggplot(aes(x, y, colour = z))+
    geom_point() +
        scale_color_manual(values = pal)) 

wrap_plots(plots, guides = "collect")

image

So what I'd like is to be able to have just one legend with B1, B2, B3, and B4. Is that possible?

almita avatar Nov 16 '24 01:11 almita

guides="collect" will only collect legends when they are identical, which for your case can be achieved by setting the limits= to include all categories. Additionally in ggplot2 >= 3.5.0 one also has to add show.legend=TRUE to the geom display a legend key for unused levels:

set.seed(10)
library(dplyr, warn = FALSE)
library(purrr)
library(ggplot2)
library(patchwork)

data <- list()
for (i in 1:4) {
  x <- rnorm(4)
  y <- rnorm(4)
  z <- sample(x = c("B1", "B2", "B3", "B4"), replace = TRUE)
  data[[i]] <- data.frame(x, y, z)
}

pal <- c("B1" = "red", "B2" = "blue", "B3" = "green", "B4" = "black")

names(data) <- c("A1", "A2", "A3", "A4")

plots <- map(data, ~ .x %>% ggplot(aes(x, y, colour = z)) +
  geom_point(show.legend = TRUE) +
  scale_color_manual(values = pal, limits = names(pal)))

wrap_plots(plots, guides = "collect")

trekonom avatar Nov 16 '24 12:11 trekonom

Yeah I figured they had to be identical, thanks for your solution!! This is very helpful

almita avatar Nov 16 '24 20:11 almita

Since this issue is still open, I take the chance to note that this becomes more of a problem if the plots you'd like to combine come from another package. Then it becomes less straight forward to modify the parameters passed to the geom, even more so if it's a custom geom (e.g. Seurat::SpatialFeaturePlot).

What is the best solution to collect guides in that case? Up until ggplot 3.5 I could resolve any issues related to collecting guides either by specifying a custom scale for all subplots or using theme, depending on the context, which wouldn't help here.

ppm1337 avatar Feb 20 '25 13:02 ppm1337