R使用for循环批量生成ggplot直方图全部显示相同数据问题排查
问题原因
你遇到的是ggplot2惰性求值的典型问题。循环过程中ggplot对象不会立即保存当时i对应的数据引用,只会记录变量名i。等循环结束后i的值已经变成9,最后渲染所有图表时,全部都读取的是df[,9]的内容。而标题是循环过程中直接计算好的固定字符串,所以显示正常。
解决方法
方法1:在for循环中强制捕获当前i的值
只需要在循环内第一行加force(i),同时建议用ggplot2推荐的.data代词引用列,避免直接用df[,i]的语法:
hist1.list <- list() for (i in 1:ncol(df)) { force(i) # 强制捕获当前迭代的i值 hist1.list[[i]] <- ggplot(df, aes(.data[[colnames(df)[i]]])) + geom_histogram(aes(y = stat(count) / sum(count)), binwidth= 0.4, color= "black", fill= "grey") + xlim(-3.7,3.7) + ylim(0,0.2) + xlab("Index Value") + ylab("Relative Frequency") + ggtitle(colnames(df)[i]) + theme_bw() + theme(plot.title = element_text(hjust = 0.5)) } do.call(grid.arrange, hist1.list)
方法2(更推荐):用长表+分面代替循环
tidyverse风格的写法更简洁,不需要手动维护循环和图表列表:
library(tidyverse) # 宽表转长表 df_long <- pivot_longer(df, cols = everything(), names_to = "模型", values_to = "Index Value") # 直接分面绘图 ggplot(df_long, aes(x = `Index Value`)) + geom_histogram(aes(y = stat(count)/sum(count)), binwidth = 0.4, color = "black", fill = "grey") + xlim(-3.7, 3.7) + ylim(0, 0.2) + xlab("Index Value") + ylab("Relative Frequency") + facet_wrap(~模型, nrow = 3) + theme_bw() + theme(strip.text = element_text(hjust = 0.5))
运行后就能得到和手动绘图一致的效果。
内容的提问来源于stack exchange,提问作者climsaver
相关产品推荐
相关产品推荐

