【问题标题】:Add a common legend under multiple ggplots with different input在具有不同输入的多个 ggplots 下添加一个公共图例
【发布时间】:2018-02-05 05:38:13
【问题描述】:

我有一个数据集的图,每个图中的过滤方式都不同。我的目标是获得一个共同的图例,其中包括图 my_hist_z、my_hist_y、my_hist_x 上显示的所有因素。

例子:

library(ggplot2); library(gridExtra); library(grid)
z <- subset(diamonds, subset = cut == "Fair" | cut == "Good")
y <- subset(diamonds, subset = cut == "Good")
x <- subset(diamonds, subset = cut == "Premium" | cut == "Fair")

colours = c("Fair" =  "#666362", 
        "Good" = "#D40511", 
        "Very Good" = "#FFCC00", 
        "Premium" = "#000000",  
        "Ideal" = "#BBBBB3") 

my_hist_z <-ggplot(z, aes(clarity, fill=cut)) + geom_bar() + 
scale_fill_manual(values = colours)
my_hist_y <-ggplot(y, aes(clarity, fill=cut)) + geom_bar() + 
scale_fill_manual(values = colours)
my_hist_x <-ggplot(x, aes(clarity, fill=cut)) + geom_bar() + 
scale_fill_manual(values = colours)

my_hist<-ggplot(diamonds, aes(clarity, fill=cut)) + geom_bar() + 
scale_fill_manual(values = colours)

可能的解决方案: https://andyphilips.github.io/blog/2017/04/04/single-legend-for-multiple-plots.html 仅使用已定义图的一个图例,但不聚合所有涉及的元素。

有什么想法吗?理想情况下,解决方案是动态的,因为这些图被描述为 for 循环的一部分。 谢谢!

【问题讨论】:

  • drop = F给你scale_fill_manual电话(即scale_fill_manual(values = colours, drop = F)),这是你要找的吗?
  • 嗨,kath,谢谢,这是一个开始。但现在它在图例上显示“非常好”,这不是任何图形 x、y、z 的一部分

标签: r plot ggplot2 legend


【解决方案1】:

首先,删除三个图例中除一个之外的所有图例,并设置参数drop = FALSE

library(ggplot2)
library(gridExtra)
library(grid)
z <- subset(diamonds, subset = cut == "Fair" | cut == "Good")
y <- subset(diamonds, subset = cut == "Good")
x <- subset(diamonds, subset = cut == "Premium" | cut == "Fair")

colours = c("Fair" =  "#666362", 
  "Good" = "#D40511", 
  "Very Good" = "#FFCC00", 
  "Premium" = "#000000",  
  "Ideal" = "#BBBBB3") 

my_hist_z <-ggplot(z, aes(clarity, fill=cut)) + geom_bar() + 
  scale_fill_manual(values = colours, drop = FALSE) + 
  theme(legend.position = "none")
my_hist_y <-ggplot(y, aes(clarity, fill=cut)) + geom_bar() + 
  scale_fill_manual(values = colours, drop = FALSE) + 
  theme(legend.position = "none")
my_hist_x <-ggplot(x, aes(clarity, fill=cut)) + geom_bar() + 
  scale_fill_manual(values = colours, drop = FALSE)

其次,使用你上面提到的post中的函数grid_arrange_shared_legend()来合并所有三个图

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(my_hist_z,my_hist_y,my_hist_x, ncol = 3)

【讨论】:

    【解决方案2】:

    这可行,但不是我想说的最优雅的解决方案:

    library(ggplot2)
    z <- subset(diamonds, subset = cut == "Fair" | cut == "Good")
    y <- subset(diamonds, subset = cut == "Good")
    x <- subset(diamonds, subset = cut == "Premium" | cut == "Fair")
    
    colours = c("Fair" =  "#666362", 
                "Good" = "#D40511", 
                "Very Good" = "#FFCC00", 
                "Premium" = "#000000",  
                "Ideal" = "#BBBBB3") 
    
    all_levels <- unique(c(levels(factor(x$cut)), levels(factor(y$cut)), levels(factor(z$cut))))
    
    x$cut <- factor(x$cut, levels = all_levels)
    y$cut <- factor(y$cut, levels = all_levels)
    z$cut <- factor(z$cut, levels = all_levels)
    
    ggplot(z, aes(clarity, fill = cut)) + geom_bar() +
      scale_fill_manual(values = colours, drop = F)
    

    编辑

    如果你所有的地块都属于同一类型,则可以将它们组合起来,然后使用facet_wrap 进行绘图:

    z$subset <- "z"
    y$subset <- "y"
    x$subset <- "x"
    
    xyz <- rbind(x, y, z)
    
    ggplot(xyz, aes(clarity, fill = cut)) + geom_bar() +
      facet_wrap(~subset) +
      scale_fill_manual(values = colours) +
      theme(legend.position = "bottom")
    

    您可以通过将strip.text = element_blank() 添加到theme 调用来隐藏构面标签。

    如果你的地块不是同一种类型,恐怕你得选择杨的解决方案。

    【讨论】:

    • 嗨,凯丝,谢谢。此外,它现在需要嵌入到一个公共绘图中,如 yang 的解决方案所示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 2018-09-24
    • 2020-05-12
    • 2019-10-29
    • 1970-01-01
    • 2022-01-18
    相关资源
    最近更新 更多