【问题标题】:multipanel ggplot from a list with grid_arrange_shared_legend带有 grid_arrange_shared_legend 的列表中的多面板 ggplot
【发布时间】:2019-04-01 20:00:23
【问题描述】:

我正在尝试通过允许用户选择要绘制的面板数量来使我的多面板 ggplotShinyApp 中的共享图例更加灵活。

目前我的代码像这样一次写出面板对象 1。

grid_arrange_shared_legend(p1,p2,p3,p4, ncol = 4, nrow = 1)

我不完全明白为什么我找不到方法告诉grid_arrange_shared_legend 接受一个地块列表(列表对象),而不是一个接一个地写出来。 它抛出这个错误:

UseMethod("ggplot_build") 中的错误: 'ggplot_build' 没有适用的方法应用于“NULL”类的对象

library(ggplot2)
library(lemon)
plotlist <- list()
dsamp <- diamonds[sample(nrow(diamonds), 300), ]
plotlist$p1 <- qplot(carat, price, data = dsamp, colour = clarity)
plotlist$p2 <- qplot(cut, price, data = dsamp, colour = clarity)
plotlist$p3 <- qplot(color, price, data = dsamp, colour = clarity)
plotlist$p4 <- qplot(depth, price, data = dsamp, colour = clarity)
grid_arrange_shared_legend(plotlist, ncol = 4, nrow = 1)

使用列表,列表中有多少个地块无关紧要,我会根据列表的长度计算 ncol 或 nrow...

【问题讨论】:

    标签: r ggplot2 lemon


    【解决方案1】:

    我的自制版本的函数通过添加 plotlist 参数并添加 plots &lt;- c(list(...), plotlist) 行作为第一行代码来实现。这样,它既可以获取绘图列表,也可以获取单独的绘图对象。

    grid_arrange_shared_legend_plotlist <- function(..., 
                                                    plotlist=NULL,
                                                    ncol = length(list(...)),
                                                    nrow = NULL,
                                                    position = c("bottom", "right")) {
    
      plots <- c(list(...), plotlist)
    
      if (is.null(nrow)) nrow = ceiling(length(plots)/ncol)
    
      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)
    }
    

    使用您的示例:

    library(gridExtra)
    library(grid)
    library(ggplot2)
    plots <- list()
    dsamp <- diamonds[sample(nrow(diamonds), 300), ]
    plots$p1 <- qplot(carat, price, data = dsamp, colour = clarity)
    plots$p2 <- qplot(cut, price, data = dsamp, colour = clarity)
    plots$p3 <- qplot(color, price, data = dsamp, colour = clarity)
    plots$p4 <- qplot(depth, price, data = dsamp, colour = clarity)
    
    grid_arrange_shared_legend_plotlist(plotlist = plots, ncol = 4)
    

    【讨论】:

    • 仍然出现同样的错误 UseMethod("ggplot_build") 中的错误:没有适用于“空”类对象的“ggplot_build”方法 grid_arrange_shared_legend_custom(plotlist, ncol = 4, nrow = 1) (给函数起一个新名字)
    • 您是否明确将 plotlist 对象传递给 plotlist 参数? (抱歉,它们的名称相同)。喜欢grid_arrange_shared_legend(plotlist = plotlist, ncol = 4)。如果你不这样做,情节列表将被...假设它是一个单独的情节对象,从而导致错误。
    • 啊是的,这就解释了。我也已经意识到“plotlist”不是虚拟代码的智能名称,在我的真实应用程序中它有一个不同的名称。我发现我愚蠢的 eval(下面的解析解决方案也很有魅力
    • 您的解决方案在阅读代码方面更令人愉悦,而且现在确实可以正常工作。小玩意儿。我会接受你的答案作为解决方案
    • 谢谢!很高兴我有点用处。回想起来,我应该从一开始就包含工作示例。从现在开始,我会牢记这一点。
    【解决方案2】:

    丑陋的文字串粘贴解决方法:

    由于提供的答案似乎不起作用,或者不合适(重建一组完全不同于我已经从大量代码中获得的绘图对象列表的绘图,我玩了一下eval(parse(text = ....) 和 @987654322 @ 动态生成一个文本字符串,该字符串最终成为完全写出的代码(有效),而无需实际写出

    nplots = 4
    nrow = 2
    ncol = ceiling(nplots/nrow)
    eval(parse( text = paste0("grid_arrange_shared_legend(", paste0("plotlist", "[[", c(1:nplots), "]]", sep = '', collapse = ','), ",ncol =", ncol, ",nrow =", nrow, ", position = 'right',  top=grid::textGrob('My title', gp=grid::gpar(fontsize=18)))", sep = '')))
    

    产生:

    [1] “grid_arrange_shared_legend(plotlist[[1]],plotlist[[2]],plotlist[[3]],plotlist[[4]],ncol =2,nrow =2, position = 'right', top=grid::textGrob('我的标题', gp=grid::gpar(fontsize=18)))"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多