使用for循环为ggplot添加不同列图层仅显示最后一项问题求助
问题根源
你遇到的问题是ggplot2的惰性求值机制导致的:aes()内部的表达式不会在循环运行时立刻计算,而是等到绘图实际渲染的时候才统一求值,此时循环变量i已经迭代到最后一个值,所以所有图层的y轴都调用了最后一个pred变量,看起来就像之前的图层被覆盖了。
解决方案1:使用整洁求值固定循环内的变量
通过rlang的符号注入操作,让aes()在每次循环时就固定当前对应的预测列,避免最后统一求值的问题:
library(ggplot2) library(data.table) library(rlang) # 提供sym、!!操作符 test <- data.table('obs'= rep(0,10), 'exp'=rnorm(10) ,'pred1'=rnorm(10), 'pred2'=rnorm(10), 'pred3'=rnorm(10), date=1:10) error_plot <- ggplot() + geom_point(aes(x=date, y = exp - obs), data = test, colour = "black") pred_names <- paste0('pred', 1:3) colours_plot <- c('green', 'blue', 'yellow') # 3个预测模型对应3个颜色即可,原代码多写了一个冗余值 for (i in 1:length(pred_names)){ error_plot <- error_plot + geom_point(aes(x=date, y = !!sym(pred_names[i]) - obs), data = test, colour = colours_plot[i]) } print(error_plot)
解决方案2(更推荐):转换为长表避免循环
ggplot2原生适配长格式数据,把不同预测列合并为同一列,直接通过颜色映射自动生成图层,不需要写循环,代码更简洁,还能自动生成图例:
library(ggplot2) library(data.table) library(tidyr) # 提供长宽表转换函数 test <- data.table('obs'= rep(0,10), 'exp'=rnorm(10) ,'pred1'=rnorm(10), 'pred2'=rnorm(10), 'pred3'=rnorm(10), date=1:10) # 宽表转长表,把所有pred列合并 test_long <- pivot_longer(test, cols = starts_with("pred"), names_to = "model", values_to = "pred_value") error_plot <- ggplot() + # 原始基准误差点 geom_point(aes(x=date, y = exp - obs), data = test, colour = "black") + # 不同模型的预测误差,自动映射颜色生成多个图层 geom_point(aes(x=date, y = pred_value - obs, colour = model), data = test_long) + # 自定义对应颜色 scale_colour_manual(values = c("pred1" = "green", "pred2" = "blue", "pred3" = "yellow")) print(error_plot)
内容的提问来源于stack exchange,提问作者Samuel Perche
相关产品推荐
相关产品推荐

