在 R 中使用 cowplot 时如何明智地对齐两个图例?

How to sensibly align two legends when using cowplot in R?

有人问了类似的问题 ,但我无法根据我的问题调整答案。

我试图在使用 cowplot 时正确对齐两个图例。例如,如果我创建一些数据和一个带有两个图例的 cowplot,如下所示:

library(cowplot)
library(ggplot2)

# create some data
dat <- NULL
for(i in 1:20){
  x <- LETTERS[1:5]
  y <- paste0("var", seq(1,5))
  dat[[i]] <- expand.grid(X=x, Y=y)
  dat[[i]]$Z <- runif(25, 0, 1)
}

# plotting function
plotFun <- function(data){
  ggplot(data, aes(X, Y, fill= Z)) + 
    geom_tile() +
    theme(aspect.ratio = 1,
          legend.justification = c(0,1),
          axis.text.x=element_blank(),
          axis.ticks.x=element_blank(),
          axis.text.y=element_blank(),
          axis.ticks.y=element_blank()) +
    xlab("") + ylab("")
}

# set up to plot on a grid
allPlots <- lapply(dat, plotFun)
allPlotsAlter <- lapply(allPlots, function(x) x + theme(legend.position = "none"))
n <- length(allPlotsAlter)
nRow <- floor(sqrt(n))
plotGrid <- gridExtra::arrangeGrob(grobs=allPlotsAlter, nrow=nRow)

# create a different type of legend
newPlot <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, fill = Species)) +
  geom_bar(stat = 'identity') + theme(legend.justification = c(0,1))

# get both legends and combine
legend  <- cowplot::get_legend(allPlots[[1]])
legend1 <- cowplot::get_legend(newPlot)
combineLegend <- cowplot::plot_grid(
  legend,
  legend1,
  nrow = 2)

# now make plot
cowplot::plot_grid(plotGrid, 
                   combineLegend, 
                   rel_widths = c(0.9, 0.11),
                   ncol = 2)

创建这种类型的情节:

如您所见,这两个图例之间有相当多的垂直 space,并且它们没有以情节为中心。

有没有办法对齐这两个图例,使它们看起来像这样:

我不确定是否可以使用 cowplot... 或者是否可以使用 ggplot 的注释来放置图例?

如果您可以选择切换到另一个包,我建议您使用 patchwork 将您的绘图粘合在一起。 patchwork 提供的一项功能是,使用 plot_spacer 您可以轻松地在图例上方和下方添加一些空白面板,以将它们“移动”到中心,从而摆脱空白 space。根据您的最终结果或最终情节的高度,您可能需要使用 heights and/or widths 参数:

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

set.seed(123)

# create some data
dat <- NULL
for (i in 1:20) {
  x <- LETTERS[1:5]
  y <- paste0("var", seq(1, 5))
  dat[[i]] <- expand.grid(X = x, Y = y)
  dat[[i]]$Z <- runif(25, 0, 1)
}

# plotting function
plotFun <- function(data) {
  ggplot(data, aes(X, Y, fill = Z)) +
    geom_tile() +
    theme(
      aspect.ratio = 1,
      legend.justification = c(0, 1),
      axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      axis.text.y = element_blank(),
      axis.ticks.y = element_blank()
    ) +
    labs(x = NULL, y = NULL)
}

# set up to plot on a grid
allPlots <- lapply(dat, plotFun)
allPlotsAlter <- lapply(allPlots, function(x) x + theme(legend.position = "none"))
n <- length(allPlotsAlter)
nRow <- floor(sqrt(n))
plotGrid <- wrap_plots(grobs = allPlotsAlter, nrow = nRow)

# create a different type of legend
newPlot <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, fill = Species)) +
  geom_bar(stat = "identity") +
  theme(legend.justification = c(0, 1))

# get both legends and combine
legend <- cowplot::get_legend(allPlots[[1]])
legend1 <- cowplot::get_legend(newPlot)

combineLegend <- plot_spacer() + legend + legend1 + plot_spacer() + plot_layout(ncol = 1, heights = c(.5, 1, 1, .5))

wrap_elements(plotGrid) + combineLegend + plot_layout(widths = c(4, 1))

我可能会按照 Stefan 的建议进行拼凑,但在 cowplot 中,您可能需要调整图例边距:

theme_margin <- theme(legend.box.margin = margin(100, 10, 100, 10))
legend  <- cowplot::get_legend(allPlots[[1]] + theme_margin)
legend1 <- cowplot::get_legend(newPlot + theme_margin)
combineLegend <- cowplot::plot_grid(
  legend,
  legend1,
  nrow = 2)

# now make plot
cowplot::plot_grid(plotGrid, 
                   combineLegend, 
                   rel_widths = c(0.9, 0.11),
                   ncol = 2)