R:使用作为对象传递的参数评估数据框中的表达式

R: Evaluate an expression in a data frame with arguments that are passed as an object

我想编写一个函数来计算数据框中的表达式,但它使用的表达式可能包含也可能不包含用户定义的对象。 我认为神奇的词是 "non-standard evaluation",但我现在还不太明白。

一个简单的例子(但对我的目的来说是现实的):比如说,我想评估一个 lm() 对在数据框中找到的变量的调用。

mydf <- data.frame(x=1:10, y=1:10)

这样做的函数可以写成如下:

f <- function(df, expr){
  expr <- substitute(expr)
  pf <- parent.frame()
  eval(expr, df, pf)
}

这样我就可以使用以下命令得到我想要的东西。

f(mydf, lm(y~x))

# Call:
# lm(formula = y ~ x)
# 
# Coefficients:
# (Intercept)            x  
#    1.12e-15     1.00e+00  

不错。但是,在某些情况下,在调用 lm() 之前将模型方程保存在对象中会更方便。不幸的是,上面的功能不再这样做了。

fml <- y~x

f(mydf, lm(fml))
# Error in eval(expr, envir, enclos): object 'y' not found

谁能解释为什么第二次调用不起作用?如何改变函数,使两次调用都能得到预期的结果? (期望=拟合模型)

干杯!

来自 ?lm,关于 data 参数:

If not found in data, the variables are taken from environment(formula)

在您的第一种情况下,公式是在您的 eval(expr, df, pf) 调用中创建的,因此公式的环境是基于 df 的环境。在第二种情况下,公式是在全局环境中创建的,这就是它不起作用的原因。

因为公式有自己的环境,所以在 NSE 中处理它们可能很棘手。

你可以试试:

with(mydf,
  {
    print(lm(y~x))
    fml <- y~x
    print(lm(fml))
  }
)

但这可能不适合您。如果不检查捕获的参数中的任何名称是否解析为公式,并重新分配它们的环境,您将遇到一些麻烦。 更糟,重新分配环境是正确的做法甚至不一定是显而易见的。在许多情况下,您确实希望查看公式环境。

在 R Chat 上有一个松散相关的讨论: