ggplot循环绘图失效:重复生成相同图表的问题排查
问题原因及解决方案
你的代码生成相同图表有两个核心问题:
1. ggplot的延迟求值导致共用变量
在for循环中,你定义了Outcome变量并在ggplot(aes(x=Outcome))中使用,但ggplot不会立即计算Outcome的值,而是在最终渲染图表时才去读取这个变量。当循环结束后,Outcome已经被赋值为最后一列的数据,所以所有图表都会使用这最后一列的数据生成。
2. 图表标题引用了错误的列名
ggtitle(colnames(ResearcherData[,i]))中的i是循环的索引(从1到8),而不是你要绘制的列的索引(colsToPlot中的61、63等),所以标题会错误地显示数据框前8列的名称,而非目标列名。
修复后的代码(方案一:改进for循环)
colsToPlot <- c(61,63,65,67,69,71,73,75) out <- list() # 先初始化空列表 for (i in 1:length(colsToPlot)){ # 获取当前要绘制的列名 current_col <- colnames(ResearcherData)[colsToPlot[i]] out[[i]] <- ResearcherData %>% # 使用.data[[colname]]明确引用当前列,避免延迟求值问题 filter(!is.na(.data[[current_col]]), .data[[current_col]] != "") %>% ggplot(aes(x = .data[[current_col]])) + geom_bar(stat = "count", fill = "#1E4D2B") + scale_x_discrete(drop=FALSE) + theme_bw() + theme( axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.title.y = element_blank(), legend.position= "none" )+ ggtitle(current_col)+ # 使用正确的列名作为标题 theme(plot.title = element_text(hjust = 0.5)) } grid.arrange(plotlist = out, ncol=2) # 用plotlist参数简化代码
修复后的代码(方案二:使用purrr包更简洁实现)
如果你熟悉purrr包,用map函数可以避免for循环的延迟求值问题,代码更简洁:
library(purrr) colsToPlot <- c(61,63,65,67,69,71,73,75) cols_names <- colnames(ResearcherData)[colsToPlot] out <- map(cols_names, function(col) { ResearcherData %>% filter(!is.na(.data[[col]]), .data[[col]] != "") %>% ggplot(aes(x = .data[[col]])) + geom_bar(stat = "count", fill = "#1E4D2B") + scale_x_discrete(drop=FALSE) + theme_bw() + theme( axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.title.y = element_blank(), legend.position= "none" ) + ggtitle(col) + theme(plot.title = element_text(hjust = 0.5)) }) grid.arrange(plotlist = out, ncol=2)
内容的提问来源于stack exchange,提问作者SBL
相关产品推荐
相关产品推荐

