R语言for循环生成ggplot结果与手动运行代码不一致问题
问题原因
这是ggplot2的惰性求值特性导致的。aes()中引用的循环变量不会在每次迭代时立即计算,而是等到调用grid.arrange渲染图表时才统一求值,此时循环已经运行完毕,变量i的值固定为循环最后一次的取值(你场景中为3),所以所有直方图都读取了rep_coefs的第三列。而labs内的x轴标签、geom_vline的截距值是在循环迭代时就计算传入的固定值,因此这两部分显示正常。
解决方法
提供3种可直接运行的修正方案:
方案1:循环内强制求值
在ggplot语句前添加force(i),强制每次迭代计算当前i的实际值:
plts1 <- list() for (i in 1:ncol(rep_coefs)) { force(i) plts1[[i]] <- ggplot(rep_coefs, aes(x = rep_coefs[[i]])) + geom_histogram(bins = 10) + geom_vline(xintercept = og_coef[[i]], color = "red") + labs(x = names(rep_coefs)[i]) } grid.arrange(grobs = plts1, nrow = 1, ncol = ncol(rep_coefs))
方案2:使用tidyverse规范的.data代词
通过.data[[列名]]的写法明确指代数据集内的列,避免惰性求值问题:
plts1 <- list() col_names <- names(rep_coefs) for (i in seq_along(col_names)) { plts1[[i]] <- ggplot(rep_coefs, aes(x = .data[[col_names[i]]])) + geom_histogram(bins = 10) + geom_vline(xintercept = og_coef[[i]], color = "red") + labs(x = col_names[i]) } grid.arrange(grobs = plts1, nrow = 1, ncol = length(col_names))
方案3:用lapply替代for循环
lapply的迭代变量天然独立,不会出现惰性求值的全局变量覆盖问题:
plts1 <- lapply(1:ncol(rep_coefs), function(i) { ggplot(rep_coefs, aes(x = rep_coefs[[i]])) + geom_histogram(bins = 10) + geom_vline(xintercept = og_coef[[i]], color = "red") + labs(x = names(rep_coefs)[i]) }) grid.arrange(grobs = plts1, nrow = 1, ncol = ncol(rep_coefs))
内容的提问来源于stack exchange,提问作者lexipalmer
相关产品推荐
相关产品推荐

