【问题标题】:extracting plots from list and add them together to use in patchwork library从列表中提取图并将它们添加在一起以在拼凑库中使用
【发布时间】:2022-09-23 05:33:58
【问题描述】:

我想使用patchwork 库来组合绘图。但我的地块保存在一个列表中。考虑下面的代码:

library(ggplot2)
library(patchwork)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))

plots_list <- list(p1, p2)

如果我使用

patchwork::wrap_plots(plots_list )

将生成下图,其中我无法控制地块之间的空间

但是,如果我想在绘图之间添加空格,我需要运行以下代码:

  p1 + plot_spacer() + p2  + plot_layout(widths = c(6, -1 ,6))

因此,我寻找一种从列表(plots_list)中提取图的方法,然后添加“+”它们并以上面的形式组合它们

    标签: r ggplot2 patchwork


    【解决方案1】:

    创建另一个列表并以编程方式将plot_spacer() 添加到奇数索引中。

    newlist <- vector("list", 2*length(plots_list) - 1)
    newlist[seq(1, 2*length(plots_list), by=2)] <- plots_list
    newlist[seq(2, 2*length(plots_list)-1, by=2)] <- replicate(length(plots_list)-1, plot_spacer(), simplify = FALSE)
    
    ### final plot
    widths <- sapply(newlist, function(L) if (inherits(L, "spacer")) -1 else 6)
    Reduce(`+`, newlist) + plot_layout(widths = widths)
    

    【讨论】:

    • 谢谢,如果有更多的情节,例如5,他们会很小。有没有办法将地块的数量限制为两列?例如,如果有 5 个图,则数组应为 3 行和 2 列?
    • plot_layout(widths=widths, nrow=ceiling(length(plots_list)/3))?
    • 似乎没有工作。这是 5 个图的数据。实际上,我想将它们排列在两个图中,并使列之间的空间更大一点: p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp)) p2 <- ggplot(mtcars) + geom_boxplot( aes(gear, disp, group = gear)) p3 <- ggplot(mtcars) + geom_bar(aes(gear)) + facet_wrap(~cyl) p4 <- ggplot(mtcars) + geom_bar(aes(carb)) p5 <- ggplot(mtcars) + geom_violin(aes(cyl, mpg, group = cyl)) plots_list <- list(P1 = p1,P2 = p2,P3 = p3, p4 = p4, p5 = p5)
    • 我现在看到了,对不起。也许wrap_plots 可以用来做到这一点,尽管我很难让它“正常工作”。
    【解决方案2】:

    第二种选择是使用 design 参数,例如design="A#B" 将在你的绘图之间添加一个间隔,当然你可以做类似paste(LETTERS[seq(length(plots_list))], collapse = "#") 的事情来以编程方式创建设计字符串。

    library(ggplot2)
    library(patchwork)
    p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
    p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
    
    plots_list <- list(p1, p2)
    
    design <- "A#B"
    
    patchwork::wrap_plots(plots_list) + plot_layout(widths = c(6, -1, 6), design = design)
    

    更新已经猜到你想要两个以上的地块。尤其是多行,这有点棘手,需要一些工作。以下是使用自定义函数根据所需行数创建design 字符串的基本方法。

    library(ggplot2)
    library(patchwork)
    p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
    p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
    
    plots_list <- list(p1, p2, p1, p2, p1)
    
    make_design <- function(x, nrows) {
      np <- length(x)
        
      ncols <- ceiling(np / nrows)
    
      design <- LETTERS[seq(np)]
      if (np %% 2 == 1) design <- c(design, rep("#", nrows * ncols - np))
      
      design <- split(design, rep(seq(nrows), each = ncols))
      design <- vapply(design, paste, collapse = "#", FUN.VALUE = character(1))
      design <- paste(design, collapse = "\n")
      
      return(design)
    }
    
    design <- make_design(plots_list, 3)
    
    patchwork::wrap_plots(plots_list) + plot_layout(widths = c(6, -1, 6), design = design)
    

    
    design <- make_design(plots_list, 2)
    
    patchwork::wrap_plots(plots_list) + plot_layout(widths = c(6, -1, 6, -1, 6), design = design)
    

    【讨论】:

    • 如果地块的数量是动态的怎么办?我应该每次都改变设计吗?我的意思是,如果我允许用​​户在两​​列内拥有灵活数量的图(例如,如果有 5 个图,则为三行两列)。那应该怎么样?
    • 我刚刚添加了一个更新以使用一个小的自定义函数创建design 字符串,该函数允许传递所需的数字行。
    猜你喜欢
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2011-08-28
    相关资源
    最近更新 更多