0

I am trying to create a ggplot scatter plot with continuous fill and discrete color. I would like to place the colorbar at the bottom and the color legend inside the panel (see image below).

ggplot(mpg, aes(x = displ, y = cty, color = manufacturer, fill = year))+
  geom_point(shape = 21) +
  theme_classic() +
  theme(legend.position = "bottom")

enter image description here

I found a solution with ggplot2::annotation_custom in combination with cowplot::as_grob and ggpubr::get_legend

# plot without the colorbar
p_nocolorbar<-
  ggplot(mpg, aes(x = displ, y = cty, color = manufacturer, fill = year))+
  geom_point(shape = 21) +
  theme_classic() +
  guides(fill = "none") +
  theme(legend.position = "bottom")

# plot without the color legend
p_nolegend<-
  ggplot(mpg, aes(x = displ, y = cty, color = manufacturer, fill = year))+
  geom_point(shape = 21) +
  theme_classic() +
  guides(color = "none") +
  theme(legend.position = "bottom")

# final plot
p_nolegend +
  annotation_custom(grob = cowplot::as_grob(ggpubr::get_legend(p_nocolorbar)),
                    xmin = 4, xmax = 7,
                    ymin = 25, ymax = 30)

enter image description here

However, this method gets a bit tidious with more complex plots and I find possitioning and scaling of the legend difficult. Wondering if anyone has a better solution.

pavlopavlin
  • 120
  • 7

1 Answers1

2

One option to simplify your code would be to work with just one plot and using guides to drop legends as needed. Second, instead of annotation_custom I would suggest to consider patchwork::inset_element which has the advantage that it allows to place the legend using relative positions instead of absolute data coordinates.

In the code below I place the legend in the topright corner with some additional padding of 5mm at the right and top. To this end I also set the legend.justification to c(1,1) aka topright before extracting the legend via cowplet::get_legend:

library(ggplot2)
library(cowplot)
library(patchwork)

p <- ggplot(mpg, aes(x = displ, y = cty, color = manufacturer, fill = year)) +
  geom_point(shape = 21) +
  theme_classic() +
  theme(legend.position = "bottom")

guide_color <- (p +
  guides(fill = "none") +
  theme(legend.justification = c(1, 1))
) |>
  cowplot::get_legend()

p +
  guides(color = "none") +
  patchwork::inset_element(guide_color,
    left = 1,
    right = unit(1, "npc") - unit(5, "mm"),
    bottom = 1, 
    top = unit(1, "npc") - unit(5, "mm")
  )

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51