如何将变量传递给已经在 R 的参数中实现非标准评估的函数?
Posted
技术标签:
【中文标题】如何将变量传递给已经在 R 的参数中实现非标准评估的函数?【英文标题】:How to pass a variable to a function which has already implement non-standard evaluation in its argument in R? 【发布时间】:2022-01-05 15:17:55 【问题描述】:我正在尝试从 R 包中封装一个函数。从源代码来看,它似乎对某些参数有非标准的评估。如何编写函数以将值传递给已实现非标准评估的参数?
这是一个玩具示例
data <- data.frame(name = 1:10)
#Suppose the one below is the function from that package
toy.fun <- function(dat, var)
eval(substitute(var), dat)
> toy.fun(data, name)
[1] 1 2 3 4 5 6 7 8 9 10
这是我尝试包装的内容
toy.fun2 <- function(dat, var2)
var_name <- deparse(substitute(var2))
#example, but for similar purpose.
data_subset <- dat[var_name]
toy.fun(data_subset, var2)
> toy.fun2(data, name)
Error in eval(substitute(var), dat) : object 'var2' not found
编辑
我应该更清楚地说明这个问题,我想将不同的变量名传递给 var2
的包装器中的函数参数。因此,当数据中有不同的变量名称时,它可以使用该名称进行数据选择,并传递给我尝试包装的函数。来自heatwaveR
的exceedance
函数的源代码已经有这个 ts_y <- eval(substitute(y), data)
来捕获输入变量y
。这相当于我的toy.fun
。
为了清楚起见,我修改了toy.fun2
。
编辑 2
事实证明,解决方案非常简单,只需替换整个函数(包括参数)并对其求值。
toy.fun2 <- function(dat, var2)
var_name <- deparse(substitute(var2))
#example, but for similar purpose.
data_subset <- dat[var_name]
exprs <- substitute(toy.fun(data_subset, var2))
eval(exprs, parent.frame())
#include `envir` argument if this is to be worked in data.table
【问题讨论】:
非标评价就是非标。适用于toy.fun
的方法不一定适用于其他一些非标准评估。您应该指定要包装的函数。
例如,@DonaldSeinen 下面的答案适用于您的示例,但可能不适用于不完全支持点参数的 tidyverse 样式的 NSE。例如。见github.com/tidyverse/glue/issues/231。
@user2554330 感谢您的建议。我已经修改了这个问题,希望这次能更清楚地说明问题。
【参考方案1】:
使用match.call
获取调用,替换函数名称并对其进行评估。
也可以根据需要修改其他参数。查看lm
的源代码以查看此方法的另一个示例。
toy.fun2 <- function(dat, var)
cl <- match.call()
cl[[1L]] <- quote(toy.fun)
eval.parent(cl)
toy.fun2(data, name)
## [1] 1 2 3 4 5 6 7 8 9 10
添加
此答案已发布后,问题已修改。这解决了新问题。行设置 cl[[2]] 也可以写成 cl[[2]] <- dat[deparse(cl[[3]])]
。
toy.fun2 <- function(dat, var2)
cl <- match.call()
cl[[1]] <- quote(toy.fun)
cl[[2]] <- dat[deparse(substitute(var2))]
names(cl)[3] <- "var"
eval.parent(cl)
toy.fun2(data, name)
## [1] 1 2 3 4 5 6 7 8 9 10
【讨论】:
这不完全是我实际问题的答案,但确实给了我一个想法。我可以substitute
整个toy.fun
函数调用,里面的变量会自动被替换。评估那个表达式会给我结果。
eval.parent(substitute(...)) 范式基本上定义了一个宏,接口由gtools包中的defmacro函数给出。以上是关于如何将变量传递给已经在 R 的参数中实现非标准评估的函数?的主要内容,如果未能解决你的问题,请参考以下文章
在 R 中,如何将参数作为字符串传递给像 plotXtabs2 这样的函数?