ggplot循环绘制多列图表存列表后图表数据异常求助
解决ggplot循环绘图后grid.arrange展示全部相同的问题
这个坑我之前踩过!核心原因是ggplot的延迟求值特性——在for循环里创建ggplot对象时,它并不会立刻把dat[,1]和dat[,2]的具体数据绑定到图表上,而是等到你真正调用(比如print()或者grid.arrange())的时候才去解析这些变量。这时候循环已经跑完了,i的值固定成了最后一次的9,所以所有图表都会用最后一次循环的dat数据。
下面给你几个可行的解决办法:
方法1:用aes_string()直接传入列名
把aes里的索引换成具体的列名字符串,这样ggplot会在循环时就把列名固定下来:
f <- list() for(i in 1:9) { cust_col <- varname.df[i,'cust'] firm_col <- varname.df[i,'firm'] dat <- subset(temp, select = c(cust_col, firm_col)) pc1 <- ggplot(dat, aes_string(y = cust_col, x = firm_col)) + geom_point() f[[i]] <- pc1 print(pc1) Sys.sleep(5) } do.call(grid.arrange,f)
方法2:用lapply()代替for循环(推荐)
lapply的每个迭代都在独立的环境中运行,不会出现延迟求值的变量共享问题:
f <- lapply(1:9, function(i) { cust_col <- varname.df[i,'cust'] firm_col <- varname.df[i,'firm'] dat <- subset(temp, select = c(cust_col, firm_col)) ggplot(dat, aes(y = .data[[cust_col]], x = .data[[firm_col]])) + geom_point() }) do.call(grid.arrange,f)
这里用.data[[colname]]是tidyverse推荐的引用列名的方式,比直接用索引更清晰。
方法3:用local()隔离循环环境
如果一定要用for循环,可以在每次迭代里用local创建独立环境,把当前的i值存下来:
f <- list() for(i in 1:9) { f[[i]] <- local({ current_i <- i cust_col <- varname.df[current_i,'cust'] firm_col <- varname.df[current_i,'firm'] dat <- subset(temp, select = c(cust_col, firm_col)) ggplot(dat, aes(y = dat[,1], x = dat[,2])) + geom_point() }) print(f[[i]]) Sys.sleep(5) } do.call(grid.arrange,f)
你提到问题已经通过第三个答案解决,应该就是用了类似local()或者隔离环境的思路~
内容的提问来源于stack exchange,提问作者Jia Gao
相关产品推荐
相关产品推荐

