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 上有一个松散相关的讨论:
我想编写一个函数来计算数据框中的表达式,但它使用的表达式可能包含也可能不包含用户定义的对象。 我认为神奇的词是 "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 上有一个松散相关的讨论: