rggplot2cowplotgrob

Move ggplot legend into title area


I have a series of paired ggplot charts I am getting to render together using cowplot. However, while the legend is useful, it's getting in the way - the charts that need legends become a lot smaller than their equivalents so you can't compare them as easily. Here's a simple example of the kind of chart I'm creating:

library(dplyr)
library(tidyr)
library(stringr)
library(tibble)
library(ggplot2)
library(cowplot)

df <- mtcars %>%
  rownames_to_column("model") %>%
  filter(str_detect(model, 'Merc')) %>%
  pivot_longer(cols = -model, names_to = 'metric') %>%
  filter(metric %in% c("hp", "drat", "wt"))

p1 <- df %>%
  filter(metric == "hp") %>%
  ggplot(aes(x = metric, y = value)) +
  geom_col() +
  facet_grid(model~.) +
  labs(title = "hp")

p2 <- df %>%
  filter(!metric == "hp") %>%
  ggplot(aes(x = metric, y = value, fill = metric)) +
  geom_col() +
  facet_grid(model~.) +
  labs(title = "drat and wt") +
  theme(legend.position = 'none')

plot_grid(p1, p2)

Which comes out looking like this:

Two sets of bar charts.  On the left, they are grey and showing hp.  On the right, they are red and blue and showing drat and wt respectively.  The area to the right of the title on the red/blue chart is manually highlighted in yellow.

I'd ideally like to drop the legend in the spot I've highlighted in yellow, since there's space, and it visually connects to the chart that needs it. But I have poked my way through assorted documentation for both ggplot2 and cowplot, but I haven't figured it out.

What am I missing?


Solution

  • We can use ggdraw(); just note that this is not exactly a robust solution and you need to tweak the position and size of the legend in the last draw_plot to get it right for your desired aspect ratio.

    p1 <- df %>%
      filter(metric == "hp") %>%
      ggplot(aes(x = metric, y = value)) +
      geom_col() +
      facet_grid(model~.) +
      labs(title = "hp")
    
    p2 <- df %>%
      filter(!metric == "hp") %>%
      ggplot(aes(x = metric, y = value, fill = metric)) +
      geom_col() +
      facet_grid(model~.) +
      labs(title = "drat and wt") +
      theme(legend.position = "top",
            legend.direction = "horizontal",
            legend.margin = margin(0, 0, 0, 0),
            legend.box.margin = margin(0, 0, 0, 0))
    
    ggdraw() +
      draw_plot(p1, 
                x = 0, y = 0, width = 0.5, height = 1) +
      draw_plot(p2 + theme(legend.position = 'none'), 
                x = 0.5, y = 0, width = 0.5, height = 1) +
      draw_plot(get_legend(p2), 
                x = 0.72, y = 0.943, width = 0.25, height = 0.07)
    

    Created on 2025-07-22 with reprex v2.1.1