【问题标题】:R: Evaluate an expression in a data frame with arguments that are passed as an objectR:使用作为对象传递的参数评估数据框中的表达式
【发布时间】:2015-04-22 17:27:23
【问题描述】:

我想编写一个函数来评估数据框中的表达式,但是使用可能包含或不包含用户定义对象的表达式来执行此操作。 我认为神奇的词是“非标准评估”,但我现在还不太清楚。

一个简单的例子(但对我的目的来说很现实):比如说,我想评估一个 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

有人可以解释为什么第二个电话不起作用吗?如何更改函数,以便两个调用都会导致预期的结果? (期望=拟合模型)

干杯!

【问题讨论】:

    标签: r object dataframe expression evaluation


    【解决方案1】:

    来自?lm,回复data 参数:

    如果在数据中找不到,则变量取自环境(公式)

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

    由于公式带有自己的环境,因此在 NSE 中处理它们可能会很棘手。

    你可以试试:

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

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

    在 R Chat 上对此问题进行了松散相关的讨论:

    【讨论】:

    • 我想我知道你的意思,尽管我会用不同的方式表达它。让我看看我是否理解这一点:问题是eval() 必须在lm() 可以作为一个整体进行评估之前寻找对象fml。由于fml 在数据框中不可用,eval 求助于在pf 中查找它。在那里找到公式是因为它是在那里创建的,但看不到 yx
    • @SimonG 问题不是eval。问题是lmenvironment(formula) 中查找变量,而不管lm 调用在哪个框架中进行评估。
    猜你喜欢
    • 2018-10-12
    • 1970-01-01
    • 2021-11-22
    • 2014-03-13
    • 1970-01-01
    • 2014-02-14
    • 2016-06-27
    • 2021-08-21
    • 1970-01-01
    相关资源
    最近更新 更多