PAYATHON 2026

R 中如何让数据掩码同时访问调用环境?

数据小陈

结论

表达式需要在数据上下文中求值,同时还要访问调用环境中的函数和对象时,可以使用 eval_tidy(),并分别传入数据和调用环境。inject() 用于注入表达式;将 as_data_mask(x) 直接作为它的求值环境,并不会让 max() 等函数自动可见。

推荐写法

library(rlang)

fn_eval <- function(x, col) {
  eval_tidy(
    expr(max({{ col }})),
    data = x,
    env = caller_env()
  )
}

df <- data.frame(A = 1:5)
fn_eval(df, A)
#> [1] 5

data = x 将数据列加入数据掩码查找,env = caller_env() 则提供调用函数时的环境,用来查找掩码中没有的名称,例如 max()。{{ col }} 保留了对裸列名 A 的注入。eval_tidy() 也支持 tidy evaluation 中使用的 .data pronoun。

为什么直接使用 inject() 会报错

题目中的 fn_inj() 将 as_data_mask(x) 作为 inject() 的 env。表达式会在这个环境中求值,但代码没有明确提供调用环境作为名称查找的后备环境,因此找不到 max()。报错 could not find function "max" 与这一原因相符。改用 base::max() 也无法解决问题,因为解析 base::max 同样需要访问 :: 的环境。

eval_tidy() 可以分别接收数据掩码和求值环境,因此不必手动把依赖的函数逐个加入掩码。

注意事项

caller_env() 指向调用 fn_eval() 时所在的环境。如果需要使用函数定义时捕获的环境,应按函数接口选择相应环境,不要假设不同调用场景的环境结构都相同。

备注:内容仅供参考。