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

如何用循环绘制多列ggplot折线图并按每页4个保存为PDF

解决ggplot批量绘图并分页输出PDF的问题

需求:处理149个序列,绘制以year为x轴的折线图,生成PDF文档,每页包含4个图。基础plot代码可正常运行,但适配ggplot时出现问题。

可正常运行的基础plot代码

dfMA <- structure(list(year = c(2000:2005),a = c(0.2569, 0.0145896,
0.0369, 0.025986, 0.12569, 
                           0.3695), b = c(0.125, 0.04582, 0.2569, 0.256369, 0.25698, 0.1456
                           ), c = c(0.2584, 0.05698, 0.1258, 0.2569, 0.098563, 0.1569)), row.names = c(NA,-6L), class = "data.frame")


pdf("test.pdf")
par(mfrow=c(2,2))

invisible(lapply(colnames(dfMA),function(x){
  plot(dfMA$year, dfMA[,x],main=x,type="l",xaxt="n", ylab = "Ring width [mm]", xlab = "", ylim=c(0,0.8)) 
  grid(nx = NULL, ny = NULL,lty = 2, col = "gray", lwd = 2) 
  axis(1, at = seq(1985, 2019, by = 2), las=2)
}))

dev.off()

原ggplot代码的问题

invisible(lapply(colnames(dfMA),function(x){
  ggplot(dfMA, aes(x=i, y = year)) + ggarrange(ncol=2,nrow=2) + geom_line() + print() 
         }))

存在的核心问题:

  • 映射关系完全错误:aes(x=i, y=year)颠倒了x/y轴,应该x为year,y为对应序列的数值
  • ggarrange用法错误:不能直接拼接在ggplot对象后,需先收集所有绘图对象再分组排版
  • 未正确引用循环变量:没有指定y轴对应dfMA中的x列
  • 缺少分页逻辑:没有处理每4个图分一页的需求

正确的ggplot解决方案

方法1:长格式数据+分面排版(简洁高效)

先将宽格式数据转为长格式,用facet_wrap自动实现每页4个图的排版:

library(tidyverse)
library(ggpubr)

# 转换为长格式数据
df_long <- dfMA %>% 
  pivot_longer(cols = -year, names_to = "series", values_to = "ring_width")

# 输出PDF
pdf("ggplot_test_facet.pdf", width = 10, height = 8)
ggplot(df_long, aes(x = year, y = ring_width)) +
  geom_line() +
  # 替代基础plot中的grid函数,添加灰色网格线
  geom_hline(yintercept = seq(0, 0.8, 0.2), lty = 2, col = "gray", lwd = 2) +
  scale_x_continuous(breaks = seq(1985, 2019, by = 2)) +
  labs(y = "Ring width [mm]", x = "") +
  # 每页4个图,按序列分面
  facet_wrap(~series, ncol = 2, nrow = 2) +
  theme_bw() +
  # 旋转x轴标签,对应基础plot的las=2
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
dev.off()

方法2:循环生成绘图对象+分组排版(灵活可控)

如果需要对每个图做个性化调整,可先循环生成所有ggplot对象,再分组排版输出:

library(ggplot2)
library(ggpubr)

# 获取所有序列列名(排除year列)
series_cols <- colnames(dfMA)[-1]

# 生成所有ggplot对象的列表
plot_list <- lapply(series_cols, function(x) {
  ggplot(dfMA, aes(x = year, y = .data[[x]])) +
    geom_line() +
    geom_hline(yintercept = seq(0, 0.8, 0.2), lty = 2, col = "gray", lwd = 2) +
    scale_x_continuous(breaks = seq(1985, 2019, by = 2)) +
    labs(title = x, y = "Ring width [mm]", x = "") +
    ylim(0, 0.8) +
    theme_bw() +
    theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
})

# 将绘图列表按每4个一组拆分
n_pages <- ceiling(length(plot_list)/4)
plot_groups <- split(plot_list, rep(1:n_pages, each=4)[1:length(plot_list)])

# 输出到PDF
pdf("ggplot_test_loop.pdf", width = 10, height = 8)
lapply(plot_groups, function(group) {
  print(ggarrange(plotlist = group, ncol = 2, nrow = 2))
})
dev.off()

说明:

  • 用.data[[x]]引用循环变量对应的列,规避ggplot非标准求值的问题
  • 两种方法均实现了每页4个图的PDF输出,方法1更简洁,方法2适合需要单独调整单图细节的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:47:02