如何对齐并避免单独创建然后添加到图中的多个图例重叠?

问题描述 投票:0回答:4

我正在尝试创建一个结合了 2 个独立图例和多个绘图网格的绘图。我遇到的问题是我发现很难对齐图例以使它们可见且不重叠。希望下面的例子能够解释我的意思。

首先,我将创建 2 个图。在这两个图中,我只对图例感兴趣,并且我放弃了实际的图(所以请忽略这两个图中的实际图)。为了获得图例,我正在使用

cowplot
包。

library(ggplot2)
library(cowplot)
# -------------------------------------------------------------------------
# plot 1 ------------------------------------------------------------------

# create fake data
dfLegend_1 <- data.frame(x = LETTERS[1:10], y = c(1:10))
# set colours
pointColours <- c(A = "#F5736A", B = "#D58D00", C = "#A0A300",
                  D = "#36B300", E = "#00BC7B", F = "#00BCC2",
                  G = "#00ADF4", H = "#928DFF", I = "#E568F0",
                  J = "#808080")

# plot
ggLegend_1 <- ggplot(dfLegend_1, aes(x=x, y=y))+
  geom_point(aes(fill = pointColours), shape = 22, size = 10) +
  scale_fill_manual(values = unname(pointColours),
                    label = names(pointColours),
                    name = 'Variable') +
  theme(legend.key.size = unit(0.5, "cm")) +
  theme_void()

# get legend
legend_1 <- get_legend(ggLegend_1)


# -------------------------------------------------------------------------
# plot 2 ------------------------------------------------------------------


# Create fake data
dflegend_2 <- data.frame(
  x = runif(100),
  y = runif(100),
  z2 = abs(rnorm(100))
)

# plot
ggLegend_2 <- ggplot(dflegend_2, aes(x=x, y = y))+
  geom_point(aes(color = z2), shape = 22, size = 10) +
  scale_color_gradientn(
    colours = rev(colorRampPalette(c('steelblue', '#f7fcfd', 'orange'))(5)),
    limits = c(0,10),
    name = 'Gradient',
    guide = guide_colorbar(
      frame.colour = "black",
      ticks.colour = "black"
    ))

# get legend
legend_2 <- get_legend(ggLegend_2)

然后我创建许多图(在本例中,我创建 20 个单独的图)并将它们绘制在网格上:

# create data
dfGrid <- data.frame(x = rnorm(10), y = rnorm(10))

# make a list of plots
plotList <- list()
for(i in 1:20){
  plotList[[i]] <- ggplot(dfGrid) +
    geom_ribbon(aes(x = x, ymin = min(y), ymax = 0), fill = "red", alpha = .5) +
    geom_ribbon(aes(x = x, ymin = min(0), ymax = max(y)), fill = "blue", alpha = .5) +
    theme_void()
}

# plot them on  a grid
gridFinal <- cowplot::plot_grid(plotlist = plotList)

最后,我将这两个图例连接在一起,并将它们添加到许多图的网格中:

# add legends together into on single plot
legendFinal <- plot_grid(legend_2, legend_1, ncol = 1)

# plot everything on the same plot
plot_grid(gridFinal, legendFinal,  rel_widths = c(3, 1))

这会产生如下所示的结果:

如您所见,图例重叠且间隔不是很好。我想知道是否有任何方法可以容纳所有内容,同时使图例适当间隔且可读?

我还应该注意,一般来说,可以有任意数量的变量和任意数量的网格图。

r ggplot2 cowplot
4个回答
5
投票

解决问题的一个选项是切换到

patchwork
将绘图和图例粘合在一起。特别是我利用
design
参数为
Variable
图例分配更多空间。但是,您应该意识到,与绘图相比,图例的灵活性要低得多,即图例的大小采用绝对单位,并且不会根据可用空间进行调整。因此,我不确定我的解决方案是否符合您对“一刀切”方法的渴望。

library(patchwork)

design <- 
"
ABCDEU
FGHIJV
KLMNOV
PQRSTV
"

plotList2 <- c(plotList, list(legend_2, legend_1))

wrap_plots(plotList2) +
  plot_layout(design = design)


2
投票

避免这种情况的一种方法是在

align = "v"
函数中添加
plot_grid()
参数,结果如下:


2
投票

基于您的图例中的颜色实际上代表图中显示的内容的大胆假设,我可以建议采用完全不同的方法来解决该问题。不要笨拙地创建完全不相关的图例,而是使用 ggplot 的自动图例创建功能,它将正确地将图例映射到您的情节美学。我想知道颜色渐变的用途是什么,但是您可以简单地使用假几何图层创建一个渐变。 (我正在使用

geom_point(shape = NA)
)。

这需要您将组(例如 A/B/C 等)正确映射到数据。完成此操作后,您将只能调用 geom_ribbon once

然后我将使用拼凑来组合您的情节,您可以收集指南。这要求所有指南(图例)完全相同。您可以通过指定

scale_
函数内的限制来确保这一点。

但是,最好使用切面。这可以通过绑定假定的几个数据帧并使用原点作为分面的 ID 来实现。

丝带看起来有点不同,因为我实际上正在绘制与 y<0 and y>0 相对应的丝带。否则,我认为 x 毫无意义。显然也可以更改以填充整个 x 限制。

library(ggplot2)
library(dplyr)
library(patchwork)

pointColours <- c(
  A = "#F5736A", B = "#D58D00", C = "#A0A300",
  D = "#36B300", E = "#00BC7B", F = "#00BCC2",
  G = "#00ADF4", H = "#928DFF", I = "#E568F0",
  J = "#808080"
)
set.seed(1)
dfGrid <- data.frame(x = rnorm(10), y = rnorm(10))

## assuming that your color mean something, and this something is represented in your legend,
## you need to map the aesthetic to your data. based on this assumption, this example
df_ribbon <-
  dfGrid %>%
  mutate(
    group = ifelse(y <= 0, pointColours["A"], pointColours["H"]),
    ## I find it better to define your ymin and ymax outside of ggplot
    ymin = ifelse(y <= 0, min(y), 0),
    ymax = ifelse(y > 0, max(y), 0)
  )

# ls_p <- rep(
rep(list(ggplot(df_ribbon) +
  ## use fill as an aesthetic
  geom_ribbon(aes(x = x, ymin = ymin, ymax = ymax, fill = I(group)), alpha = .5) +
  ## fake geom_layer
  geom_point(aes(x = min(x), y = min(y), color = y), shape = NA, na.rm = T) +
  scale_color_gradientn(
    colours = rev(colorRampPalette(c("steelblue", "#f7fcfd", "orange"))(5)),
    limits = c(0, 10),
    name = "Gradient",
    guide = guide_colorbar(
      frame.colour = "black",
      ticks.colour = "black"
    )
  ) +
  scale_fill_manual(
    values = unname(pointColours),
    label = names(pointColours),
    ## important to add limits
    limits = pointColours,
    name = "Variable"
  ) +
    theme_void()), 20) %>%
  ## now merge the legends
  patchwork::wrap_plots() +
  plot_layout(guide = "collect")


0
投票

将图例一起添加到单个绘图中时,您可以尝试使用参数

align
rel_heights
来调整位置:

legendFinal <- plot_grid(legend_2, legend_1, align = "hv", ncol = 1, rel_heights = c(1, 3))

之后,合并图:

plot_grid(gridFinal, legendFinal, rel_widths = c(3, 1))

它在我的机器上运行良好。

© www.soinside.com 2019 - 2024. All rights reserved.