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

R语言批量生成多页5×3布局图表问题求助

问题求助:批量生成带统计信息的图表并分多页布局

需求说明

  • 遍历文件夹中所有CSV文件,为每个文件生成SOC随时间变化的图表
  • 将计算得到的Mean SOC、TNPP、ANPP、BNPP等统计信息添加到图表中
  • 按5×3布局自动分多页排列所有图表

测试环境

拥有一批包含time(时间)、somtc(SOC)、agcprd(AGBM)、bgcjprd(BGBM)字段的CSV测试文件


尝试方法与问题分析

方法1:基础plot函数

path <- "C:/Users/.../trialFiles" 
dfs <- dir(path, "*.csv", full.names = FALSE, ignore.case = TRUE, all.files = TRUE) 

plotModel <- function(df) { 
  dat <- read.csv(paste(path, df, sep = "/"), header = TRUE, sep = ",") 
  Time <- dat$time 
  SOC <- dat$somtc 
  AGBM <- dat$agcprd 
  BGBM <- dat$bgcjprd 
  
  time_frame <- Time >= oT & Time <= fT 
  sTime <- Time[time_frame] 
  sSOC <- SOC[sTime] 
  sAGBM <- AGBM[sTime] 
  sBGBM <- BGBM[sTime] 
  
  iM_AGBM <- mean(sAGBM) 
  iM_BGBM <- mean(sBGBM) 
  iMSOC <- mean(sSOC) 
  iTNPP <- sum(iM_AGBM, iM_BGBM) 
  
  plot(Time, SOC) 
  legend("bottomright", bty = "n", legend = paste(df, "\n\n", "SOC =", format(iMSOC, digits = 6), "\n", "TNPP =", format(iTNPP, digits = 6), "\n", "ANPP =", format(iM_AGBM, digits = 5), "\n", "BNPP =", format(iM_BGBM, digits = 5), sep = "")) 
} 

eq_plot <- lapply(dfs, plotModel) 
nPlot <- length(eq_plot) 
cols <- 3 
layout <- matrix(seq(1, cols * ceiling(nPlot/cols)), ncol = cols, nrow = ceiling(nPlot/cols)) 

grid.newpage() 
pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout)))) 
for (i in 1:nPlot) { 
  matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE)) 
  print(eq_plot[[i]], vp = viewport(layout.pos.row = matchidx$row, layout.pos.col = matchidx$col)) 
} 

问题原因:基础plot函数是直接绘图的函数,没有返回值(eq_plot列表里全是NULL),后续用grid布局调用print时没有可输出的图表内容,所以只显示了提前绘制的图例。


方法2:ggplot2 + ggpubr

dfs <- dir(period, "*.csv", full.names = FALSE, ignore.case = TRUE, all.files = TRUE) 

plotModel <- function(df) { 
  dat <- read.csv(paste(period, df, sep = "/"), header = TRUE, sep = ",") 
  Time <- dat$time 
  SOC <- dat$somtc 
  AGBM <- dat$agcprd 
  BGBM <- dat$bgcjprd 
  
  time_frame <- Time >= oT & Time <= fT 
  sTime <- Time[time_frame] 
  sSOC <- SOC[sTime] 
  sAGBM <- AGBM[sTime] 
  sBGBM <- BGBM[sTime] 
  
  iM_AGBM <- mean(sAGBM) 
  iM_BGBM <- mean(sBGBM) 
  iMSOC <- mean(sSOC) 
  iTNPP <- sum(iM_AGBM, iM_BGBM) 
  
  ggplot(dat, aes(x=Time, y=SOC)) + 
    geom_line() + 
    ggtitle(df, subtitle = paste("SOC =", format(iMSOC, digits = 6), "\n", "TNPP =", format(iTNPP, digits = 6), "\n", "ANPP =", format(iM_AGBM, digits = 5), "\n", "BNPP =", format(iM_BGBM, digits = 5), sep = "")) 
} 

eq_plot <- lapply(dfs, plotModel) 
multi.page <- ggarrange(eq_plot, nrow = 5, ncol = 3) 
ggexport(multi.page, filename = "diag_plots") 

问题原因:

  1. period变量未定义(应该替换为文件路径变量path)
  2. ggarrange需要通过plotlist参数传入ggplot对象列表,直接传eq_plot会导致类型识别错误,从而抛出ggplot2 doesn't know how to deal with data of class uneval

修复后的解决方案

方案1:基础plot函数实现分多页布局

改用layout函数直接控制多图布局,同时支持分页(每页5×3):

path <- "C:/Users/.../trialFiles" 
dfs <- dir(path, "*.csv", full.names = FALSE, ignore.case = TRUE, all.files = TRUE) 

# 定义时间范围(需要根据你的数据调整)
oT <- 0
fT <- 100

plotModel <- function(df) { 
  dat <- read.csv(file.path(path, df), header = TRUE, sep = ",") 
  Time <- dat$time 
  SOC <- dat$somtc 
  AGBM <- dat$agcprd 
  BGBM <- dat$bgcjprd 
  
  time_frame <- Time >= oT & Time <= fT 
  sSOC <- SOC[time_frame] 
  sAGBM <- AGBM[time_frame] 
  sBGBM <- BGBM[time_frame] 
  
  # 加na.rm避免空值导致计算失败
  iM_AGBM <- mean(sAGBM, na.rm = TRUE) 
  iM_BGBM <- mean(sBGBM, na.rm = TRUE)
  iMSOC <- mean(sSOC, na.rm = TRUE)
  iTNPP <- iM_AGBM + iM_BGBM 
  
  # 绘制折线图,添加标题和图例
  plot(Time, SOC, type = "l", main = df, xlab = "Time", ylab = "SOC")
  legend("bottomright", bty = "n", 
         legend = c(paste("SOC =", format(iMSOC, digits = 6)),
                    paste("TNPP =", format(iTNPP, digits = 6)),
                    paste("ANPP =", format(iM_AGBM, digits = 5)),
                    paste("BNPP =", format(iM_BGBM, digits = 5))))
} 

# 分页处理:每页15个图表(5行×3列)
page_size <- 15
dfs_pages <- split(dfs, ceiling(seq_along(dfs)/page_size))

for(page in dfs_pages){
  layout(matrix(1:15, ncol = 3, nrow = 5))
  lapply(page, plotModel)
  # 如果要导出为文件,可在此处添加dev.print(pdf, paste0("page_", which(dfs_pages == page), ".pdf"))
}

方案2:ggplot2 + ggpubr实现分多页PDF导出

修复参数错误并优化代码:

library(ggplot2)
library(ggpubr)

path <- "C:/Users/.../trialFiles" 
dfs <- dir(path, "*.csv", full.names = FALSE, ignore.case = TRUE, all.files = TRUE) 

# 定义时间范围
oT <- 0
fT <- 100

plotModel <- function(df) { 
  dat <- read.csv(file.path(path, df), header = TRUE, sep = ",") 
  Time <- dat$time 
  SOC <- dat$somtc 
  AGBM <- dat$agcprd 
  BGBM <- dat$bgcjprd 
  
  time_frame <- Time >= oT & Time <= fT 
  sSOC <- SOC[time_frame] 
  sAGBM <- AGBM[time_frame] 
  sBGBM <- BGBM[time_frame] 
  
  iM_AGBM <- mean(sAGBM, na.rm = TRUE)
  iM_BGBM <- mean(sBGBM, na.rm = TRUE)
  iMSOC <- mean(sSOC, na.rm = TRUE)
  iTNPP <- iM_AGBM + iM_BGBM 
  
  # 整理副标题文本
  sub_text <- paste0("SOC = ", format(iMSOC, digits = 6), "\n",
                     "TNPP = ", format(iTNPP, digits = 6), "\n",
                     "ANPP = ", format(iM_AGBM, digits = 5), "\n",
                     "BNPP = ", format(iM_BGBM, digits = 5))
  
  ggplot(dat, aes(x = Time, y = SOC)) + 
    geom_line(color = "#2c3e50") + 
    ggtitle(df) +
    labs(subtitle = sub_text, x = "Time", y = "SOC") +
    theme_bw() +
    theme(plot.subtitle = element_text(size = 9))
} 

# 生成ggplot对象列表
eq_plot <- lapply(dfs, plotModel) 

# 按5×3布局生成多页图表
multi.page <- ggarrange(plotlist = eq_plot, nrow = 5, ncol = 3) 

# 导出为多页PDF
ggexport(multi.page, filename = "diag_plots.pdf")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:51:23