ggplot: combine legends of different datasets

44 views Asked by At

In the plot below, you see two datasets plotted together using ggplot. The first dataset uses geom_pointrange() and the second one geom_ribbon() and geom_line(). As I haven't found a way to show the legend together in the same plot, I produced two separate plots, from which I took the legend and I combined the legend using plot_grid(). The only issue is that there is a vectical space before the legend that I cannot remove (see yellow highlighted part). Do you know how? Or is there a simpler way to achieve what I described?

Plot

Here is the code:

library(ggplot2)
library(cowplot)

#datasets
d1=data.frame(x=c(0,5,8),y=c(1.2,5.5,8),ymin=c(1.2,5.5,8)-1,ymax=c(1.2,5.5,8)+1,col=factor("Data1"))
d2=data.frame(x=0:9,y=1+0:9,ymin=0.5+0:9,ymax=1.5+0:9,col=factor("Data2"))

#main plot
plot = ggplot()+
  geom_ribbon(data = d2,
              aes(x=x,y=y,ymin=ymin,ymax=ymax),
              fill="black", alpha=0.1) +
  geom_line(data=d2,aes(x=x,y=y),
            col="black",size=1)+
  geom_pointrange(data=d1,
                  aes(x=x,y=y,ymin=ymin,ymax=ymax),
                  col="darkred",
                  linewidth=1,size=0.5)

#legends
legend1 = get_legend(ggplot()+
  geom_pointrange(data=d1,
                  aes(x=x,y=y,ymin=ymin,ymax=ymax,col=col,fill=col),
                  linewidth=1,size=0.5)+
    scale_color_manual(name="",values="darkred")+
    scale_fill_manual(name="",values="darkred")+
    theme(plot.margin = unit(c(0,0,0,0), "cm")))
legend2 = get_legend(d2 %>% 
  ggplot(aes(x=x,y=y,ymin=ymin,ymax=ymax,fill=col))+
  geom_ribbon(alpha=0.2) +
  geom_line(aes(col=col),size=1)+
  scale_color_manual(values="black",name="") +
  scale_fill_manual(values="black",name="")+
  theme(plot.margin = unit(c(0,0,0,0), "cm")))

#plot with legends
cowplot::plot_grid(plot+theme(plot.margin = unit(c(0,0,0,0), "cm")),
                   cowplot::plot_grid(legend1,
                                      legend2,
                                      ncol=2,nrow=1),
                   rel_heights=c(12,1),ncol=1,nrow=2)
1

There are 1 answers

0
stefan On

I think there are easier options to achieve your desired result, e.g. you could use the ggnewscale package to add a second color scale and some tweaking via theme options.

Note: By default there is some white space too between the axis title and the legend box which I removed via legend.box.spacing = unit(0, "pt"). So this might work as well for your cowplot approach.

library(ggplot2)

ggplot(mapping = aes(x = x, y = y)) +
  geom_ribbon(
    data = d2,
    aes(ymin = ymin, ymax = ymax, fill = "Data2"),
    alpha = 0.1
  ) +
  geom_line(
    data = d2,
    aes(col = "Data2"),
    size = 1
  ) +
  scale_color_manual(
    values = "black", name = NULL,
    guide = guide_legend(order = 2)
  ) +
  scale_fill_manual(
    values = "grey25", name = NULL,
    guide = guide_legend(order = 2)
  ) +
  ggnewscale::new_scale_color() +
  geom_pointrange(
    data = d1,
    aes(ymin = ymin, ymax = ymax, col = "Data1"),
    linewidth = 1, size = 0.5
  ) +
  scale_color_manual(
    values = "darkred", name = NULL,
    guide = guide_legend(order = 1)
  ) +
  theme(
    legend.position = "bottom",
    legend.box.spacing = unit(0, "pt"),
    legend.margin = margin(l = 60, r = 60),
    legend.key = element_rect(fill = NA)
  )