R 'ggplot2' Arranging common and unique legends with multiple (gridded) plot objects.

时间秒杀一切 提交于 2019-12-11 15:20:15

问题


edit - reproducible example included below

I have been using this function with the ggplot2 package to Add a common Legend for combined ggplots which works perfecty when each plot has only 1 type of legend e.g. for ...,color =, ....

However, I am trying to arrange multiple plots which share a common legend but each has an additional unique legend e.g.:

  ggplot(df1, aes(x=Site, y=RESULT, color=Position , shape=DETNAME)) +
        geom_point(size=5) + ylab ("concentration (mg/L)") +
        labs (shape = "Determinand")

which produces :

I have 3x these where the Position legend is shared but the Determinand legends are unique.

So I want to know if there is an additional argument I can pass to grid_arrange_shared_legend() which will preserve the Determinand legends (shape = DETNAME) i.e. plotting them above each plot on the grid using something like legend.position = "top" but having a common legend for Position (color = position) ?

I know I can add + guides(shape = FALSE ) to each plot object and then use grid_arrange_shared_legend() which gives me the shared Position legend, but I want to achieve something like this but with a unique Determinand legend for each plot:

Or could any one advise which part of the source code for the grid_arrange_shared_legend() function needs editing to perform this?

edit - reproducible example

  library (ggplot2)
  library(gridExtra)
  library (grid)

   # two ggplot plot objects with multiple legends 1 common legend and 2 unique

  p1<- ggplot(diamonds, aes(x=price, y= depth, color= clarity , shape= cut )) +
    geom_point(size=5) + labs (shape = "unique legend", color = "common legend")

  p2 <- ggplot(diamonds, aes(x=price, y= depth, color= clarity , shape= color )) +
 geom_point(size=5) + labs (shape = "unique legend", color = "common legend")

   # shared legend function

  grid_arrange_shared_legend <- function(..., ncol = length(list(...)), nrow     = 1, position = c("bottom", "right")) {

    plots <- list(...)
    position <- match.arg(position)
    g <- ggplotGrob(plots[[1]] + theme(legend.position = position))$grobs
    legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
    lheight <- sum(legend$height)
    lwidth <- sum(legend$width)
    gl <- lapply(plots, function(x) x + theme(legend.position="none"))
    gl <- c(gl, ncol = ncol, nrow = nrow)

    combined <- switch(position,
                 "bottom" = arrangeGrob(do.call(arrangeGrob, gl),
                                        legend,
                                        ncol = 1,
                                        heights = unit.c(unit(1, "npc") -  lheight, lheight)),
                       "right" = arrangeGrob(do.call(arrangeGrob, gl),
                                       legend,
                                       ncol = 2,
                                       widths = unit.c(unit(1, "npc") - lwidth, lwidth)))

    grid.newpage()
    grid.draw(combined)

    # return gtable invisibly
    invisible(combined)

    }

    grid_arrange_shared_legend (p1,p2)

Using the grid_arrange_shared_legend() function here means that the unique legend is correct only for one of the plots on the grid

Question How to preserve (extract?) the unique legends and plot them above each plot on the grid but keep the common legend at the bottom?


回答1:


I would advise using cowplot here. In this case it's easiest to combine two plot_grid calls, then get the legend with get_legend:

library(ggplot2)

#reduce the number of points to plot
diamonds2 <- diamonds[sample(nrow(diamonds), 500), ]

p1<- ggplot(diamonds2, aes(x=price, y= depth, color= clarity , shape= cut )) +
  geom_point(size=5) + labs (shape = "unique legend", color = "common legend") +
  theme(legend.position = "top")

p2 <- ggplot(diamonds2, aes(x=price, y= depth, color= clarity , shape= color )) +
  geom_point(size=5) + labs (shape = "unique legend", color = "common legend") +
  theme(legend.position = "top")

cowplot::plot_grid(
  cowplot::plot_grid(
    p1 + scale_color_discrete(guide = FALSE),
    p2 + scale_color_discrete(guide = FALSE),
    align = 'h'
  ),
  cowplot::get_legend(p1 + scale_shape(guide = FALSE) + theme(legend.position = "bottom")),
  nrow = 2, rel_heights = c(4, 1)
)



来源:https://stackoverflow.com/questions/46832287/r-ggplot2-arranging-common-and-unique-legends-with-multiple-gridded-plot-obj

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!