ggplot2中!!(bang bang)语法失效问题求助
解决ggplot2动态列名在旧版本R/rlang环境中的报错问题
你遇到的这个错误完全是因为环境版本兼容性问题——你的R 3.4.4、rlang 0.2.0都是比较老旧的版本,这些版本里的tidyverse语法和现在的新版本有不少差异,尤其是非标准求值(NSE)的实现逻辑。
为什么会报错?
你看到的Error in !as.name(nomes[1]) : invalid argument type,本质上是因为旧版本的rlang对!!(bang-bang)解引用运算符的支持不完善。在这个版本里,解析器没有把!!当成特殊的解引用符号,反而拆成了两个独立的逻辑取反运算符!,而as.name()返回的是一个符号对象,不是可以取反的逻辑值,自然就报错了。
几种可行的解决方案
方案1:用rlang旧版本的UQ()替代!!
在rlang 0.2.0中,官方推荐的解引用函数是UQ()(Unquote),而不是!!。把代码里的!!换成UQ()就能正常运行:
library(tidyverse) library(rlang) Q <- as_tibble(data.frame(series = rep(c("diax","diay"),3), value = c(3.25,3.30,3.31,3.36,3.38,3.42), year = c(2018,2018,2019,2019,2020,2020))) %>% select(year, series, value) %>% spread(key = "series", value = "value") %>% rename(`2018-01-01` = diax, `2017-01-01` = diay) nomes <- c("2018-01-01","2017-01-01") ggplot(Q, aes(x = year)) + geom_line(aes(y = UQ(as.name(nomes[1]))), col = "red", size = 2, linetype = "dotdash") + geom_line(aes(y = UQ(as.name(nomes[2]))), col = "orange", size = 2, linetype = "dashed")
方案2:改用aes_string()传递字符串列名
旧版本的ggplot2提供了aes_string()函数,专门用来接受字符串形式的列名,不需要额外的解引用操作,这种写法对你的环境更友好:
library(tidyverse) Q <- as_tibble(data.frame(series = rep(c("diax","diay"),3), value = c(3.25,3.30,3.31,3.36,3.38,3.42), year = c(2018,2018,2019,2019,2020,2020))) %>% select(year, series, value) %>% spread(key = "series", value = "value") %>% rename(`2018-01-01` = diax, `2017-01-01` = diay) nomes <- c("2018-01-01","2017-01-01") ggplot(Q, aes(x = year)) + geom_line(aes_string(y = nomes[1]), col = "red", size = 2, linetype = "dotdash") + geom_line(aes_string(y = nomes[2]), col = "orange", size = 2, linetype = "dashed")
方案3:升级环境(长期最优解)
如果你的工作允许,建议升级到较新的R版本(比如R 4.0+),同时更新tidyverse和rlang到最新稳定版。新版本里!!sym()或者!!as.name()的写法完全可以正常运行,而且能获得更多新功能和bug修复。不过升级前记得备份你的工作环境,避免依赖包的兼容性问题。
内容的提问来源于stack exchange,提问作者motabe
相关产品推荐
相关产品推荐

