如何在RMarkdown生成的PDF中正确展示循环生成的DataFrame?
解决RMarkdown循环生成课程KPI表格不显示的问题
核心问题原因
RMarkdown中循环内的表格输出不会自动触发渲染,必须明确调用适配PDF的渲染函数;另外你代码里的effectif计算存在错误,会导致统计结果失真。
修复步骤与代码
1. 修正统计逻辑错误
把effectif = nrow(test_colonne_no_na[1])改为effectif = nrow(test_colonne_no_na),否则你得到的永远是1,无法正确统计有效人数。
2. 收集结果后统一渲染(推荐方案)
循环内先把每个课程的统计结果存入列表,循环结束后用knitr::kable统一生成适配PDF的表格,这是最稳定的方式:
library(dplyr) library(knitr) library(kableExtra) ## CREATION DE LA BOUCLE/FONCTION # Tableau par cours cours_subset = subset(data, select = (num_inscr_prog_ulb+1):ncol(data)) cours_subset = cours_subset[, colSums(is.na(cours_subset[1, ])) == 0] moyenne_cours = cours_subset[5,] cours_subset = cours_subset[-1:-5,] # 初始化列表存储所有课程的统计结果 course_summaries <- list() # début de la boucle for (a in 1:ncol(cours_subset)) { test_colonne = cours_subset[,a] #boucler sur le nombre de colonne nom_colonne = colnames(test_colonne[1]) test_colonne_no_na = subset(test_colonne, !is.na(test_colonne[,1])) # 修正effectif计算 effectif = nrow(test_colonne_no_na) count_abs = 0 count_abj = 0 count_ndp = 0 count_ann = 0 count_else = 0 grades = NULL for (i in 1:effectif) { valeur = test_colonne_no_na[i, 1] if (valeur == "ABS") { count_abs = count_abs + 1 } else if (valeur == "ABJ") { count_abj = count_abj + 1 } else if (valeur == "NDP") { count_ndp = count_ndp + 1 } else if (valeur == "ANN") { count_ann = count_ann + 1 } else { count_else = count_else + 1 grades = c(grades, valeur) } } grades = gsub(",", ".", grades) grades_num = as.numeric(grades) nombre_de_zero = length(subset(grades_num, grades_num == 0)) moyenne_du_cours = round(mean(na.omit(grades_num)),3) moyenne_du_cours_sans_zero = round(mean(subset(grades_num, grades_num != 0)), 3) noms_df = c("Cours analysé", "Effectif", "NDP", "ABS", "ABJ", "ANN", "Elèves ayant passé l'examen", "Moyenne", "Nombre d'élèves ayant eu 0", "Moyenne sans les 0") valeurs_df = c(nom_colonne, effectif, count_ndp, count_abs, count_abj, count_ann, count_else, moyenne_du_cours, nombre_de_zero, moyenne_du_cours_sans_zero) summary_cours = data_frame(Description = noms_df, Valeur = valeurs_df) # 将当前课程的统计结果加入列表 course_summaries[[nom_colonne]] <- summary_cours } # 循环输出所有课程的表格 for (course_name in names(course_summaries)) { # 添加课程标题 cat(paste0("## KPI du cours : ", course_name, "\n")) # 生成PDF适配的表格 print( kable(course_summaries[[course_name]], format = "latex", booktabs = TRUE, caption = paste("Statistiques détaillées pour", course_name)) %>% kable_styling(latex_options = c("striped", "hold_position")) ) # 添加空行分隔表格 cat("\n\n") }
3. 循环内实时输出(备选方案)
如果坚持在循环内输出每个表格,需用knitr::kable配合print,并确保输出格式正确:
在循环内替换print(pander(summary_cours))为:
cat(paste0("### ", nom_colonne, "\n")) print(knitr::kable(summary_cours, format = "latex", booktabs = TRUE)) cat("\n")
额外优化建议
替换内层循环统计状态的逻辑,用向量操作更高效:
# 统计各状态人数 count_abs = sum(test_colonne_no_na[,1] == "ABS", na.rm = TRUE) count_abj = sum(test_colonne_no_na[,1] == "ABJ", na.rm = TRUE) count_ndp = sum(test_colonne_no_na[,1] == "NDP", na.rm = TRUE) count_ann = sum(test_colonne_no_na[,1] == "ANN", na.rm = TRUE) # 提取成绩 grades = test_colonne_no_na[!test_colonne_no_na[,1] %in% c("ABS","ABJ","NDP","ANN"), 1] count_else = length(grades)
这样可以去掉内层的for循环,大幅提升代码运行效率。
内容的提问来源于stack exchange,提问作者Lucien
相关产品推荐
相关产品推荐

