【问题标题】:Passing function argument to formula将函数参数传递给公式
【发布时间】:2014-09-10 00:27:02
【问题描述】:

我试图理解为什么

foo = function(d,y,x) {
    fit = with(d, lm(y ~ x))
}
foo(myData, Y, X)

不起作用,例如在哪里

myData = data.frame(Y=rnorm(50), X=runif(50))

对我来说似乎很棘手的一点是将参数 xy 传递给公式,如 lm(y ~ x)

【问题讨论】:

标签: r


【解决方案1】:

@DMT 的回答很好地解释了发生了什么。

如果您希望事情按预期工作,可以跳过以下步骤:

lmwrap <- function(d,y,x) {
    ys <- deparse(substitute(y))
    xs <- deparse(substitute(x))
    f <- reformulate(xs,response=ys)
    return(lm(f,data=d))
}
mydata <- data.frame(X=1:10,Y=rnorm(10))
lmwrap(mydata,Y, X)

或者,如果您将列名作为字符串而不是符号传递,则可以稍微简化一下。

lmwrap <- function(d,y,x) {
    f <- reformulate(xs, response=ys)
    return(lm(f, data=d))
}
lmwrap(mydata, "Y", "X")

这种方法会有点脆弱,例如如果您通过另一个函数传递参数。此外,让公式的“呼叫”部分读取Y~X 需要更多技巧......

【讨论】:

  • 我还想到了类似getfn&lt;-function(x, y) { f&lt;-eval(as.call(list(quote(~), substitute(x), substitute(y)))) ;environment(f)&lt;-parent.frame(); f} 来制作公式。但我想这与reformulate() 非常接近,只需跳过字符串化步骤即可。但在你发布之前,我不知道reformulate() 存在。
  • 对于y 似乎不需要deparse(),即ys &lt;- substitute(y) 也可以。我对 DMT 答案的批评是​​关于它的普遍性,因为它假设我只关心 lm()lm(),而问题是如何将函数 lmwrap 的参数传递到公式中。
  • 直接传递公式会更好吗?喜欢lmwrap(y ~ x, d)。不过,我不知道如何将y~x 传递给lm。很高兴听到关于这部分的详细说明。
【解决方案2】:

Y 和 X 是您的列名,而不是变量。在这种情况下,它们不会成为函数的参数,除非您将它们作为字符串传递并本质上调用

lm(mydata[,"Y"]~ mydata[,"X"])

如果您要在控制台上运行 ls(),Y 和 X 很可能不存在,因此该函数将无法工作。在 fit = 调用之前打印 x 和 y,您可能会看到 NULL,它不会在 lm 中飞行。

在您的表单中执行此操作的一种方法如下

lmwrap<-function(df, yname, xname){
fit=lm(d[,yname] ~ d[,xname])
}

lmwrap(mydata,"Y", "X")

但你可以像常规一样进行 lm 调用

【讨论】:

  • 是的,但是当您将调用包装在一个函数中时,您现在尝试将 Y 的“值”传递给小 y,并将 X 的“值”传递给小 x。 y 和 x 将采用传递给它们的变量的值,在您的情况下,这很可能是 null。在全局环境中进行 with 调用时,您可以绕过函数中发生的值传递过程,并且 R 能够将 Y 与 mydata$Y 绑定,对于 X 也是如此。抱歉,如果我解释得不好
  • 所以你的评论有点解释了为什么函数调用失败;但它并没有解决如何做到这一点的问题——它肯定可以做到。
  • 您可以在函数中复制您的问题,方法是说 y=Y 和 x=X 然后调用 with(mydata y~x)
  • “只需拨打lm 常规电话”——这不是重点!我希望能够传递两个参数——这里是yx 到一个公式中——这不一定是lm() !!!这就是 MWE 应该做的,我在我的问题中表示了这一点,然后在我的评论中再次表示。在myData1 中说,感兴趣的变量是var1' and var2; and in myData2`,变量是AB。你的回答没有解决问题。
  • 但@DMT 已经非常清楚地解释了(IMO)发生了什么,他们在回答中提供的功能表明,如果您愿意将变量放在引号中标记一切都可以正常工作。 (我同意他们的最后一行不太有用。)
猜你喜欢
  • 2013-01-18
  • 2020-03-04
  • 2013-01-27
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
相关资源
最近更新 更多