You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将if/else循环生成的ggplot图形存入列表并通过ggarrange排版

问题描述

背景

通过大量if/else循环用ggplot2生成图形,每个图形按固定规则命名为唯一对象,示例命名如下:

graph_log_bar_blue <- 
graph_log_violin_blue <-
graph_log_bar_red <-
graph_log_violin_red <-
graph_log_bar_green <-
graph_log_violin_green <-

希望将满足循环条件生成的图形存入列表,以便用ggpubr包的ggarrange或gridExtra进行面板排版。但目前用ls(pattern = "graph_")仅能得到图形名称字符串,无法直接用于排版:

graph_list <- ls(pattern = "graph_") # 仅列出图形名称,未存储图形对象

library("ggpubr")
ggarrange(graph_list,
          nrow = 1, ncol = 3)

# 或使用gridExtra
library("gridExtra")                                              # 加载gridExtra包
do.call("grid.arrange", c(plot_list, ncol = 3)) 

具体疑问

  • 是否可以创建ggplot生成的图形列表?
  • 如何在if/else循环内筛选或创建图形列表?
  • 如何调用生成的图形并使用ggarrange(ggpubr包)等工具排版为面板图?

数据示例代码

使用iris数据集模拟实际代码结构(逻辑无需深究):

library(ggplot2)
iris <- iris
#数据集1
kt <- kruskal.test(Petal.Width ~ Species, data = iris)
kt$p.value
if(kt$p.value > 0.05){
  pt <- pairwise.wilcox.test(iris$Petal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt$p.value < 0.05){
  graph_log_bar_blue <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species)) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar") +
    geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5) +
    labs(x=NULL, y= "Petal Width (cm)")
}else{
  graph_log_violin_blue <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species)) +
    geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6) +
                  labs(x=NULL,
                       y= "Petal Width (cm)")
}


#数据集2
kt_sep <- kruskal.test(Sepal.Width ~ Species, data = iris)
kt_sep$p.value
if(kt_sep$p.value > 0.05){
  pt_sep <- pairwise.wilcox.test(iris$Sepal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt_sep$p.value > 0.05){
  graph_log_bar_red <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species)) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar") +
    geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5) +
    labs(x=NULL, y= "Sepal Width (cm)")
}else{
  graph_log_violin_red <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species)) +
    geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6) +
    labs(x=NULL,
         y= "Sepal Width (cm)")
}

graph_list <- ls(pattern="graph_")

解决方案

方法一:在循环/条件语句中直接构建图形列表(推荐)

避免单独创建大量全局环境变量,生成图形时直接添加到列表,更高效且条理清晰:

library(ggplot2)
library(ggpubr)

# 初始化空列表
graph_list <- list()

# 数据集1处理
kt <- kruskal.test(Petal.Width ~ Species, data = iris)
if(kt$p.value > 0.05){
  pt <- pairwise.wilcox.test(iris$Petal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt$p.value < 0.05){
  p <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species)) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar") +
    geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5) +
    labs(x=NULL, y= "Petal Width (cm)")
  # 添加到列表并指定名称
  graph_list[["graph_log_bar_blue"]] <- p
}else{
  p <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species)) +
    geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6) +
    labs(x=NULL, y= "Petal Width (cm)")
  graph_list[["graph_log_violin_blue"]] <- p
}

# 数据集2处理(修正原代码重复条件问题)
kt_sep <- kruskal.test(Sepal.Width ~ Species, data = iris)
if(kt_sep$p.value > 0.05){
  pt_sep <- pairwise.wilcox.test(iris$Sepal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt_sep$p.value < 0.05){
  p <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species)) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar") +
    geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5) +
    labs(x=NULL, y= "Sepal Width (cm)")
  graph_list[["graph_log_bar_red"]] <- p
}else{
  p <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species)) +
    geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6) +
    labs(x=NULL, y= "Sepal Width (cm)")
  graph_list[["graph_log_violin_red"]] <- p
}

# 直接用列表排版
ggarrange(plotlist = graph_list, nrow = 1, ncol = length(graph_list))

方法二:从全局环境提取已有图形对象到列表

如果已经生成了单独的图形对象,用mget()函数将名称字符串转换为实际图形对象:

# 提取所有以graph_开头的对象到列表
graph_list <- mget(ls(pattern = "^graph_"))

# 用ggarrange排版(需指定plotlist参数)
ggarrange(plotlist = graph_list, nrow = 1, ncol = 2)

# 或用gridExtra包
library(gridExtra)
do.call(grid.arrange, c(graph_list, ncol = 2))

关键说明

  • ggplot对象本质是R列表,完全可以存入列表,方法一从源头构建列表更高效,还能避免全局环境变量混乱。
  • mget()是解决“只有名称无对象”问题的核心,它能根据变量名称字符串从环境中提取对应对象。
  • ggarrange需要通过plotlist参数接收图形列表,不能直接传入字符串列表;gridExtra的grid.arrange可通过do.call将列表元素作为参数传入。

内容的提问来源于stack exchange,提问作者MM1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:30:58