首页 文章

将非标准评估参数传递给子集函数

提问于
浏览
1

我想在另一个函数中使用 subset ,但是从顶级函数传递非标准的求值参数 . 以下是非工作代码,但概述了这个想法:

foo_1 <- function(x, mysubset) 
{
  # some deparse, substitute etc. magic here ??
  subset(x, subset)
}
foo_1(ansombe, x1 > 5)

我希望这能得到与 subset(ansombe, x1 > 5) 相同的结果 . 此外,我希望在将参数传递到更深层次时也能正常工作,即

foo_2 <- function(x, mysubset) 
{  
  # some deparse, substitute etc. magic here ??
  foo_1(x, mysubset)
}
foo_2(ansombe, x1 > 5)

在这里我也想要与上面相同的结果 .

What I have tried so far

我试过 substitute - deparseeval - parse 组合,就像

foo_1 <- function(x, mysubset)
{
  tx <- deparse(substitute(mysubset))
  subset(x, eval(parse(text=tx)))
}
foo_1(anscombe, x1 >5)

这很好,但我现在如何继续_1872139?

另外,我记得Thomas Lumley的格言:

如果答案是解析(),您通常应该重新考虑这个问题 . - Thomas Lumley(R-help,2005年2月)

所以,我想知道是否有一个比 eval - parse 组合更好的方法 . 有任何想法吗?

PS . 这个问题类似,但不包括更深的嵌套:Pass subset argument through a function to subset

PPS:从 plyr 应用 . 函数可能很有成效,但我不知道如何...

3 回答

  • 4

    只要你尽可能地延迟评估,这样的事情应该有效

    foo_1 <- function(x, mysubset) 
    {
      do.call("subset", list(quote(x), substitute(mysubset)))
    }
    
    foo_2 <- function(x, mysubset) 
    {  
      do.call("foo_1", list(quote(x), substitute(mysubset)))
    }
    
    data(anscombe)
    foo_1(anscombe, x1 > 5)    
    foo_2(anscombe, x1 > 5)
    

    但是如果你计划用 mysubset 进行捣乱,你需要更加小心 . 这将有助于确切知道你为什么要这样做 .

  • 2

    可能有龙 . (但那些也隐藏在 subset 中 . )

    foo_1 <- function(x, mysubset) 
    { 
      sub <- eval(substitute(mysubset), envir=x, enclos=parent.frame())
      x[sub,]
    }
    
    foo_1(iris, Sepal.Length == 5 & Species == "setosa")
    #   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    #5             5         3.6          1.4         0.2  setosa
    #8             5         3.4          1.5         0.2  setosa
    #26            5         3.0          1.6         0.2  setosa
    #27            5         3.4          1.6         0.4  setosa
    #36            5         3.2          1.2         0.2  setosa
    #41            5         3.5          1.3         0.3  setosa
    #44            5         3.5          1.6         0.6  setosa
    #50            5         3.3          1.4         0.2  setosa
    
  • 2

    我认为你不能避免 eval ,但你可以避免 parse . 只需在函数内重建对 subset 的调用:

    foo_1 <- function(x, mysubset) {
      eval(call("subset", x, substitute(mysubset)), parent.frame())
    }
    foo_1(mtcars, cyl == 6 & mpg > 20)
    #                 mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Mazda RX4      21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
    # Mazda RX4 Wag  21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
    # Hornet 4 Drive 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
    

相关问题