在R中为多页PDF添加标注时出现空白PDF及报错的求助
问题:多页PDF添加标注时生成空白文件并报错
问题现象
- 单页PDF添加标注可正常生成
- 无标注的多页PDF能正常输出
- 为多页PDF添加标注时,生成空白PDF并抛出错误:
Error in gList(list(`1` = list(data = list(), layers = list(<environment>, : only 'grobs' allowed in "gList"
数据示例
Sample_ID <- c("P1014B", "P1014F", "P1036A") SCORE <- c(1500,2000,2500) SCORE2 <- c(1254, 2100,2550) SCORE3 <- c(1599, 1900, 2533) SCORE4 <- c(1400, 1995, 2400) SCORE5 <- c(1376, 2300, 2600) df<- data.frame(Sample_ID, SCORE, SCORE2,SCORE3,SCORE4, SCORE5)
原代码示例
fn<- c("file1","file2","file3","file4") for (i in 1:length(fn)){ df<- read_tsv(fn[i]) colors<- c("Lower Limit 1500" = "red") a <- ggplot(df,aes(x=Sample_ID,y=`SCORE2`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE2`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 2000" = "red") b <- ggplot(df,aes(x=Sample_ID,y=`SCORE3`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[2]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE3`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 2500" = "red") c <- ggplot(df,aes(x=Sample_ID,y=`SCORE4`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE4`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 1500" = "red") d <- ggplot(df,aes(x=Sample_ID,y=`SCORE5`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE5`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) ############ create the pdf ############# with annotation one page works pdf(file=paste0(fn[1]," with annotation one page.pdf")) figure <- ggarrange(a, b + font("x.text", size = 10), ncol = 1, nrow = 2) annotate_figure(figure, top = text_grob(paste0("QC Report ",fn[1]," "), color = "red", face = "bold", size = 14), bottom = text_grob( paste0("Date of run: ", my_date, " "), color = "#80919E", hjust = 1, x = 1, face = "italic", size = 10) ) dev.off() } ############# without annotation two page works pdf(file=paste0(fn[1]," without annotation two page.pdf")) figure<-(ggarrange(a, b , ncol = 1, nrow = 2, ggarrange(c, d, ncol=1,nrow=2) )) print(figure) dev.off() ############# with annotation two page doesn't work pdf(file=paste0(fn[1]," with annotation two page.pdf")) figure<-(ggarrange(a, b , ncol = 1, nrow = 2, ggarrange(c, d, ncol=1,nrow=2) )) annotate_figure(figure, top = text_grob(paste0("QC Report ",fn[1]," "), color = "red", face = "bold", size = 14), bottom = text_grob( paste0("Date of run: ", my_date, " "), color = "#80919E", hjust = 1, x = 1, face = "italic", size = 10)) dev.off()
报错原因
annotate_figure仅支持处理单页的ggarrange对象。当嵌套ggarrange生成多页复合对象时,它无法识别这种结构,导致抛出"only 'grobs' allowed in 'gList'"错误,同时因为没有正确渲染内容,生成空白PDF。
另外原代码存在一处逻辑错误:循环中始终使用fn[1]而非fn[i],会导致所有输出文件都复用第一个文件名,需修正。
解决方案
方法:拆分页面分别添加标注后输出
将图表按页面分组排版,给每个单页的ggarrange对象单独添加标注,再依次打印到PDF中:
fn<- c("file1","file2","file3","file4") # 假设my_date已定义,示例用系统日期 my_date <- Sys.Date() for (i in 1:length(fn)){ df<- read_tsv(fn[i]) # 生成图表a-d的代码保持不变 colors<- c("Lower Limit 1500" = "red") a <- ggplot(df,aes(x=Sample_ID,y=`SCORE2`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE2`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 2000" = "red") b <- ggplot(df,aes(x=Sample_ID,y=`SCORE3`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[2]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE3`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 2500" = "red") c <- ggplot(df,aes(x=Sample_ID,y=`SCORE4`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE4`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) colors<- c("Lower Limit 1500" = "red") d <- ggplot(df,aes(x=Sample_ID,y=`SCORE5`)) + geom_bar( stat="identity", fill="cyan4") + geom_hline(aes(yintercept=SCORE[1]), col = colors, size = 1.5, linetype=2, show.legend = TRUE) + geom_text(aes(label = `SCORE5`), nudge_y=4) + ggtitle("Median Score") + theme(plot.title = element_text(hjust = 0.5)) + scale_colour_manual(values=colors) # 分页面组合图表 page1 <- ggarrange(a, b, ncol=1, nrow=2) page2 <- ggarrange(c, d, ncol=1, nrow=2) # 给每个页面添加标注 annotated_page1 <- annotate_figure(page1, top = text_grob(paste0("QC Report\n",fn[i],"\n"), color = "red", face = "bold", size = 14), bottom = text_grob( paste0("Date of run: \n ", my_date, " "), color = "#80919E", hjust = 1, x = 1, face = "italic", size = 10)) annotated_page2 <- annotate_figure(page2, top = text_grob(paste0("QC Report\n",fn[i],"\n"), color = "red", face = "bold", size = 14), bottom = text_grob( paste0("Date of run: \n ", my_date, " "), color = "#80919E", hjust = 1, x = 1, face = "italic", size = 10)) # 输出多页PDF pdf(file=paste0(fn[i]," with annotation two page.pdf")) print(annotated_page1) print(annotated_page2) dev.off() }
关键修正点
- 将嵌套的ggarrange拆分为独立单页对象,分别用
annotate_figure处理 - 修正循环中文件名引用错误:将
fn[1]改为fn[i],确保每个输入文件对应正确的输出PDF - 用
print()显式打印每个标注后的页面,确保PDF正常渲染内容
内容的提问来源于stack exchange,提问作者user483292
相关产品推荐
相关产品推荐

