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")
问题原因:
period变量未定义(应该替换为文件路径变量path)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
相关产品推荐
相关产品推荐

