如何实现类似R语言base包with()的自定义函数?
实现类似
with()的自定义函数解决方案 要实现允许直接引用数据框列名的自定义函数,核心是处理非标准求值(NSE),让函数参数能在数据框的上下文中解析。以下是几种可行方法:
方法1:使用rlang的大括号操作符{{}}(推荐)
利用rlang的{{}}(注入操作符)将用户传入的列表达式直接注入到with()的上下文中,修正参数写法即可:
library(rlang) mean_diff <- function(data, x, y) { with(data, mean({{x}}) - mean({{y}})) } # 测试运行 mean_diff(mtcars, x = am, y = vs) #> [1] -0.03125
你之前的代码错误在于mean(x = x)——这里的第一个x是mean()函数的参数名,第二个x是自定义函数的参数,而非数据框列名。直接使用{{x}}会将用户传入的列表达式(比如am)注入到mean()的参数位置,实现正确解析。
方法2:用rlang的eval_tidy直接求值
不依赖with(),直接用eval_tidy在数据框上下文中求值表达式:
library(rlang) mean_diff <- function(data, x, y) { eval_tidy(expr(mean({{x}}) - mean({{y}})), data = data) } mean_diff(mtcars, x = am, y = vs) #> [1] -0.03125
方法3:Base R原生实现(无需额外包)
用substitute()捕获用户传入的表达式,再用eval()在数据框环境中求值:
mean_diff <- function(data, x, y) { # 捕获列表达式 x_col <- substitute(x) y_col <- substitute(y) # 在数据框环境中求值并计算差值 eval(expr(mean(!!x_col) - mean(!!y_col)), envir = data) } mean_diff(mtcars, x = am, y = vs) #> [1] -0.03125
或者更简洁的Base R写法:
mean_diff <- function(data, x, y) { x_vec <- eval(substitute(x), data) y_vec <- eval(substitute(y), data) mean(x_vec) - mean(y_vec) }
内容的提问来源于stack exchange,提问作者Daniel D. Sjoberg
相关产品推荐
相关产品推荐

