RMarkdown循环生成多PDF但图表重复问题排查求助
批量生成班级PDF报告的错误分析与修正
核心错误点
1. RMarkdown未使用传递的参数,全局读取全量数据
执行脚本通过params给每个报告传递了当前班级的t1/t2文件路径及班级名称,但RMarkdown完全忽略这些参数,直接读取固定的Dataframe.csv全量数据,导致所有报告基于同一数据源生成。
2. RMarkdown内循环遍历所有班级,仅保留最后一次循环的图表
RMarkdown里写了遍历所有班级的循环,每次循环都会覆盖text_plot变量,最后只输出循环结束时text_plot存储的最后一个班级的图表,因此所有PDF显示的都是最后一个班级的结果。
3. 拼写错误导致数据处理异常
代码中textscores_long$school_class <- as.character(textscores_long$schoolclass)存在拼写错误:schoolclass应为school_class,这会导致班级列转换失败,后续过滤逻辑失效。
修正后的代码
执行脚本(路径确认正确即可,无需修改)
# Path to the data data_path <- "Datapath" # Function for rendering PDFs render_pdf <- function(csv_file_t1, csv_file_t2) { # Extract file name (without path and extension) class <- tools::file_path_sans_ext(basename(csv_file_t1)) # Remove the suffix “_work_t1” from the variable “class” class <- gsub("_work_t1$", "", class) # Debugging: Check whether class was defined correctly print(paste("Class:", class)) # Render R Markdown document with parameters rmarkdown::render( input = "Datapath/report.Rmd", # Path to the Rmd file output_file = paste0("Report_", class, ".pdf"), params = list( class = class, file_t1 = csv_file_t1, file_t2 = csv_file_t2 ), envir = new.env(parent = globalenv()) ) } # List of CSV files for t1 csv_files_t1 <- list.files(path = data_path, pattern = "*_work_t1.csv", full.names = TRUE) # Loop for rendering all PDFs for t1 and t2 for (file_t1 in csv_files_t1) { # Find the corresponding t2 file file_t2 <- gsub("_t1.csv$", "_t2.csv", file_t1) if (file.exists(file_t2)) { print(paste("Process file:", file_t1, "and", file_t2)) render_pdf(file_t1, file_t2) # Use current file_t1 and file_t2 } else { print(paste("No corresponding t2 file found for:", file_t1)) } }
修正后的RMarkdown绘图代码
# --- # params: # class: "" # file_t1: "" # file_t2: "" # --- # 1. 使用传递的参数读取当前班级的t1和t2数据 t1_data <- read.csv2(params$file_t1) t2_data <- read.csv2(params$file_t2) # 合并t1和t2数据(替换为实际主键,如student_id) Dataframe <- merge(t1_data, t2_data, by = "student_id") # 2. 过滤当前班级且consent=1的记录 textscores <- subset(Dataframe, consent == 1 & school_class == params$class) %>% select(school_class, ExCon, text_scores_T1, text_scores_T2) # 3. 转换为长格式 textscores_long <- textscores %>% rename("August 2023" = text_scores_T1, "February 2024" = text_scores_T2) %>% pivot_longer(cols = c("August 2023", "February 2024"), names_to = "MP", values_to = "Textscores") # 修正拼写错误 textscores_long$school_class <- as.character(textscores_long$school_class) # 4. 生成当前班级的图表(无需遍历所有班级) # 当前班级均值 df1 <- textscores_long %>% group_by(school_class, MP) %>% summarise(Mean = mean(Textscores, na.rm = TRUE)) %>% mutate(grp = "school_class") %>% rename("name" = school_class) %>% mutate(name = "Your class") # 读取全量数据计算实验组/对照组均值 full_data <- read.csv2("Dataframe.csv") full_textscores <- subset(full_data, consent == 1) %>% select(school_class, ExCon, text_scores_T1, text_scores_T2) %>% rename("August 2023" = text_scores_T1, "February 2024" = text_scores_T2) %>% pivot_longer(cols = c("August 2023", "February 2024"), names_to = "MP", values_to = "Textscores") df2 <- full_textscores %>% group_by(ExCon, MP) %>% summarise(Mean = mean(Textscores, na.rm = TRUE)) %>% mutate(grp = "ExCon") %>% rename("name" = ExCon) %>% mutate(name = ifelse(name == "实验", "Experimental group", "Control group")) # 替换为实际分组值 # 合并数据并绘图 text_plot <- rbind(df1, df2) %>% ggplot(aes(x = MP, y = Mean, fill = name)) + geom_col(position = position_dodge()) + scale_fill_manual(values = c("orange", "steelblue", "steelblue1"), name = NULL) + theme_classic() # 输出图表 text_plot
关键说明
- RMarkdown开头必须声明
params参数,确保能接收执行脚本传递的值。 - 每个报告仅处理当前班级的数据,无需遍历所有班级,避免变量被覆盖。
- 实验组/对照组的全局均值需从全量数据计算,保证对比基准正确。
- 合并t1和t2数据时,务必使用正确的主键(如学生ID),避免数据错位。
内容的提问来源于stack exchange,提问作者sunny
相关产品推荐
相关产品推荐

