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

Posted

技术标签:

【中文标题】将非标准评估参数传递给子集函数【英文标题】:Passing on non-standard evaluation arguments to the subset function 【发布时间】:2015-02-17 10:45:59 【问题描述】:

我想在另一个函数中使用subset,但要传递来自***函数的非标准评估参数。以下是非工作代码,但概述了这个想法:

foo_1 <- function(x, mysubset) 

  # some deparse, substitute etc. magic here ??
  subset(x, subset)

foo_1(ansombe, x1 > 5)

我希望得到与subset(ansombe, x1 &gt; 5) 相同的结果。另外,当参数传递到更深层次时,我希望同样的工作,即

foo_2 <- function(x, mysubset) 
  
  # some deparse, substitute etc. magic here ??
  foo_1(x, mysubset)

foo_2(ansombe, x1 > 5)

这里我也想要和上面一样的结果。

到目前为止我已经尝试过什么

我尝试了substitute-deparseeval-parse 组合,比如

foo_1 <- function(x, mysubset)

  tx <- deparse(substitute(mysubset))
  subset(x, eval(parse(text=tx)))

foo_1(anscombe, x1 >5)

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

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

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

所以,我想知道是否有比eval-parse 组合更好的方法。? 有什么想法吗?

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

PPS:也许应用plyr 中的. 函数很有成效,但我不知道如何......

【问题讨论】:

当一个简单的foo[foo[,1]&lt;5,] 或类似的结构可以使用时,我不太喜欢使用subset。如果您可以发布一些小的、可重复的示例数据,我们可以展示一个简单的方法来做到这一点。编辑:就像 BrodieG 所做的 :-) 【参考方案1】:

我不认为你可以避开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    

【讨论】:

【参考方案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

【讨论】:

@BrodieG 嘿,别惹我们坦格利安人。【参考方案3】:

只要你尽可能延迟评估,这样的事情应该可以工作

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 混在一起,则需要更加小心。确切地知道您为什么这样做会有所帮助。

【讨论】:

以上是关于将非标准评估参数传递给子集函数的主要内容,如果未能解决你的问题,请参考以下文章

Python 仅将非 None 的参数传递给函数

将非静态成员函数作为参数传递给另一个类中的成员函数

如何将非硬编码参数传递给 Python 装饰器?

作为参数传递时如何评估函数

markdown 将非原始参数传递给Apex方法的问题

将 now() 作为参数传递给函数时如何进行评估