在 R 中编写函数时向 lm 函数传递参数

7

我希望能在函数内调用lm,并指定weights变量作为传递给外部函数的参数,然后再传递给lm。下面是一个可重现的示例,如果在函数外部调用lm,则可以正常工作,但如果从包装函数中调用,则会产生错误消息Error in eval(expr, envir, enclos) : object 'weightvar' not found

olswrapper <- function(form, weightvar, df){
  ols <- lm(formula(form), weights = weightvar, data = df)
  }

df <- mtcars

ols <- lm(mpg ~ cyl + qsec,  weights = gear, data = df)
summary(ols)

ols2 <- olswrapper(mpg ~ cyl + qsec,  weightvar = gear, df = df)
#Produces error: "Error in eval(expr, envir, enclos) : object 'weightvar' not found"

当你输入 gear 时会得到什么?什么也没有,因为它没有被全局定义,而且你的 olswrapper 不知道在 df 中查找它。让它工作的一种方法是将 weightvar = "gear" 作为字符传递,然后在你的 lm 调用中使用 weights = df[weightvar] - Gregor Thomas
3个回答

3

继续上面的评论,gear没有全局定义。它可以在独立的lm调用中使用,因为您指定了要使用的数据,所以lm知道从df中取出gear

但是,在那个独立的lm函数之外,gear本身不存在。这由gear的输出证明。

> gear
Error: object 'gear' not found

您可以使用 df$geargear 传递到函数中。
weightvar <- df$gear
ols <- olswrapper(mpg ~ cyl + qsec, weightvar , df = df)

为什么将 df$gear 直接传递给包装器会产生相同的错误,而这种方式的行为不同? - Michael

2
我知道我来晚了,但我认为之前的解释是不完整的。声明weightvar < - df$gear,然后将其传递给函数只能起作用,因为您将weightvar用作权重参数的名称。这只是将weightvar用作全局变量。这就是为什么df$gear不能直接工作的原因。如果使用除weightvar以外的任何名称,它也不起作用。
它不起作用的原因是lm在两个位置查找数据:数据框参数(如果指定)和公式环境。在这种情况下,您的公式环境是R_GlobalEnv。(您可以通过从olswrapper内部运行print(str(form))来测试这一点。)因此,lm只会在全局环境和df中查找,而不是函数环境。
编辑:在lm文档中,数据参数的描述如下: “一个可选的数据框、列表或环境(或可由as.data.frame强制转换为数据框的对象),其中包含模型中的变量。如果在数据中找不到,则从environment(formula)中获取变量,通常是从lm调用的环境。”
一个快速的解决方法是说environment(form) < - environment()来更改您的公式环境。这不会引起任何问题,因为公式中的数据在您指定的数据框中。

2
在函数体内使用

eval(substitute(...))可以让我们使用非标准的评估方法。

df <- mtcars
olswrapper <- function(form, weightvar, df)
  eval(substitute(ols <- lm(formula(form), weights = weightvar, data = df)))
  summary(ols)

olswrapper(mpg ~ cyl + qsec,  weightvar = gear, df = df)

更多内容请参见: http://adv-r.had.co.nz/Computing-on-the-language.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接