在自定义函数中通过管道整合dplyr与ggplot2的报错问题咨询
解决管道连接dplyr与ggplot2的自定义函数问题
我来帮你搞定这个管道连接的问题!你的核心需求是把filter和ggplot直接用管道串起来,不用中间变量tmp对吧?问题出在非标准评估(NSE)的语法兼容上,原来的aes_()是旧语法,而且在管道里变量引用的环境会有变化,我给你两个靠谱的解决方案:
方案1:用{{ }}(Curly-Curly)简化写法(推荐)
这是tidyverse最新的tidyeval语法,代码最简洁直观:
foo <- function(df, y, t = 4){ df %>% filter({{y}} > t) %>% ggplot(aes(x = {{y}})) + geom_histogram() } # 测试调用,和你原来的效果完全一致 foo(mtcars, cyl)
方案2:用enquo() + !!的经典tidyeval写法
如果需要兼容更早版本的tidyverse包,可以用这种写法,更清晰地看到变量捕获的过程:
foo <- function(df, y, t = 4){ # 先捕获函数参数y的表达式和环境 y_var <- enquo(y) df %>% filter(!!y_var > t) %>% ggplot(aes(x = !!y_var)) + geom_histogram() }
为什么原来的管道写法会报错?
你原来尝试直接管道时,应该是用了aes_(substitute(y)),这里的问题在于:
aes_()是ggplot2的旧版NSE语法,现在官方已经推荐用aes()结合tidyeval操作符了- 在管道链中,
substitute(y)的执行环境不是函数的参数环境,它没法正确捕获你传入的cyl这类变量名,导致ggplot找不到对应的变量,自然就报错了
而enquo()会专门捕获函数参数的表达式和它所在的环境,!!则是把捕获的变量“注入”到filter和ggplot的表达式中,{{ }}则是enquo() + !!的语法糖,让代码更简洁。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

