R语言ggplot2 for循环绘图后grid.arrange调用fill着色失效问题求助
问题根源
这个问题是ggplot2的延迟求值特性导致的:aes()中定义的映射关系不会在你创建ggplot对象时立即计算,只会在实际渲染绘图时才会读取对应变量的当前值。你在循环中定义的rightans是全局环境变量,循环执行完成后rightans会停留在最后一次迭代的取值,后续不管是调用grid.arrange拼接图表,还是单独调用之前保存的ggplot对象,都会用这个最终值计算fill着色规则,因此所有图的着色逻辑都和最后一张图一致。
另外你的代码还存在一个隐藏问题:你给fill属性做了映射,但调用的是scale_colour_manual修改颜色色板,就算fill逻辑正常也无法显示预期的红绿配色,需要改成scale_fill_manual。
解决方案
有两种常用的修复方案可任选:
方案1:用非标准求值注入变量值
使用rlang的!!操作符,在创建ggplot对象时就把当前迭代的rightans值直接注入到aes表达式中,避免后续渲染时再读取变量:
plist<-list() for (i in 1:20){ TheTable <- answers[i] %>% count(answers[i]) colnames(TheTable) <- c("q", "n") rightans <- correct_answers[i] perc_wrong <- prop.table(table(right_wrong[i]))[1]*100 p<-ggplot(TheTable)+ # 用!!注入当前rightans的取值 geom_bar(stat="identity", aes(x=q, y=n, fill = q == !!rightans)) + # 把colour改成fill scale_fill_manual(name = 'Right', values = setNames(c('green','red'), c(T, F)))+ theme_classic()+ theme(legend.position='none')+ xlab("")+ ylab("")+ labs(title= paste0("Question ", i, " (", rightans, ") "), subtitle=paste0(round(perc_wrong, 0), "% was wrong")) print(p) plist[[i]]<-p assign(paste0("Q", i, "_plot"), p) } do.call(grid.arrange,plist)
方案2:封装绘图逻辑为独立函数
将单张图表的生成逻辑封装为独立函数,利用函数的局部作用域锁定每次迭代的参数值,不会被后续循环的变量覆盖:
# 定义绘图函数 make_single_plot <- function(i, answers, correct_answers, right_wrong) { TheTable <- answers[i] %>% count(answers[i]) colnames(TheTable) <- c("q", "n") rightans <- correct_answers[i] perc_wrong <- prop.table(table(right_wrong[i]))[1]*100 p<-ggplot(TheTable)+ geom_bar(stat="identity", aes(x=q, y=n, fill = q == rightans)) + scale_fill_manual(name = 'Right', values = setNames(c('green','red'), c(T, F)))+ theme_classic()+ theme(legend.position='none')+ xlab("")+ ylab("")+ labs(title= paste0("Question ", i, " (", rightans, ") "), subtitle=paste0(round(perc_wrong, 0), "% was wrong")) return(p) } # 循环调用函数生成图表 plist<-list() for (i in 1:20) { p <- make_single_plot(i, answers, correct_answers, right_wrong) print(p) plist[[i]] <- p assign(paste0("Q", i, "_plot"), p) } do.call(grid.arrange,plist)
内容的提问来源于stack exchange,提问作者Thomas Frissen
相关产品推荐
相关产品推荐

