ggplot2: multiple plots in a single row with a single legend

吃可爱长大的小学妹 提交于 2019-11-30 19:35:22

Why don't you use facetting?

library(reshape2)
dmelt <- melt(dsamp, id.vars = c("price", "clarity"), measure.vars = c("carat", "depth"))
ggplot(dmelt, aes(x = price, y = value, color = clarity)) +
  geom_point() +
  facet_wrap(~ variable, scales = "free")

I usually use facet_wrap or facet_grid as @Roland suggested.

A while ago I had to use the grid.arrange (I wanted the labels on the y-axis to be colored in an specific order) and this is the function I came up with:

ggplot_shared_info <- function(...) {
  plots <- list(...)
  g <- ggplotGrob(plots[[1]])$grobs
  legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
  title <- g[[grep("plot.title", sapply(g, function(x) x$name))]]
  xaxis <- g[[grep("axis.title.x", sapply(g, function(x) x$name))]]
  yaxis <- g[[grep("axis.title.y", sapply(g, function(x) x$name))]]

  lwidth <- sum(legend$width)
  theight <- sum(title$height)
  xheight <- sum(xaxis$height)
  ywidth <- sum(yaxis$width)

  grid.arrange(
     title,
     arrangeGrob(
       yaxis,
       do.call(arrangeGrob, c(lapply(plots, function(x)
         x + theme(legend.position="none", 
                   plot.title = element_blank(),
                   axis.title = element_blank())), 
         nrow = 1)),
       legend,
       nrow = 1,
       widths = grid::unit.c(ywidth, unit(1, "npc") - ywidth - lwidth, lwidth)
     ),
     xaxis, 
     heights = grid::unit.c(theight, unit(1, "npc") - theight - xheight, xheight),
     ncol = 1
  )
}

Edit: now user can determine which of the listed plot elements should be 'joined'.

ggplot_shared_info <- function(..., elements = c('legend', 'title', 'yaxis', 'xaxis')) {
  plots <- list(...)
  g <- ggplotGrob(plots[[1]])$grobs

  legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
  lwidth <- sum(legend$width)
  title <- g[[grep("plot.title", sapply(g, function(x) x$name))]]
  theight <- sum(title$height)  
  xaxis <- g[[grep("axis.title.x", sapply(g, function(x) x$name))]]
  xheight <- sum(xaxis$height)
  yaxis <- g[[grep("axis.title.y", sapply(g, function(x) x$name))]]
  ywidth <- sum(yaxis$width)

  plots <- lapply(plots, function(x, elements = elements){
    if('legend' %in% elements) x <- x + theme(legend.position="none")
    if('title' %in% elements) x <- x + theme(plot.title = element_blank())
    if('xaxis' %in% elements) x <- x + theme(axis.title.x = element_blank())
    if('yaxis' %in% elements) x <- x + theme(axis.title.y = element_blank())
    x
  }, elements = elements)
  plots <- do.call(arrangeGrob, c(plots, nrow = 1))

  if('legend' %in% elements) 
    plots <- arrangeGrob(plots, legend, nrow = 1, widths = grid::unit.c(unit(1, "npc") - lwidth, lwidth))
  if('yaxis' %in% elements)
    plots <- arrangeGrob(yaxis, plots, nrow = 1, widths = grid::unit.c(ywidth, unit(1, "npc") - ywidth))
  if('title' %in% elements) 
    plots <- arrangeGrob(title, plots, ncol = 1, heights = grid::unit.c(theight, unit(1, "npc") - theight))
  if('xaxis' %in% elements)     
    plots <- arrangeGrob(plots, xaxis, ncol = 1, heights = grid::unit.c(unit(1, "npc") - xheight, xheight))
  grid.arrange(plots)
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!