如何do.call使用变量参数和函数列表来使用summarise_dplyr中的标准评估版本?
## Some sample data, function, and variables to interpolate
set.seed(0)
dat <- data.frame(a=runif(10), b=runif(10))
fn <- function(x, y) IQR(x / y, na.rm = TRUE)
funs <- list(fn="fn")
targs <- list("a", "b")
Run Code Online (Sandbox Code Playgroud)
这是lazyeval::interp我正在努力工作
library(dplyr)
interp(~do.call(fn, xs), .values=list(fn=funs$fn, xs=targs))
# ~do.call("fn", list("a", "b"))
Run Code Online (Sandbox Code Playgroud)
但它不起作用,
dat %>%
summarise_(out = interp(~do.call(fn, xs), .values=list(fn=funs$fn, xs=targs)))
Run Code Online (Sandbox Code Playgroud)
预期结果
dat %>%
summarise(out = do.call(fn, list(a, b)))
# out
# 1 1.084402
Run Code Online (Sandbox Code Playgroud)
如果我添加一些打印语句,我知道问题是"a"和"b"没有被正确解释,但我无法弄清楚如何正确引用它们.
fn <- function(x, y) { print(x); print(y); IQR(x / y, na.rm = TRUE) }
dat %>%
summarise_(out = interp(~do.call(fn, xs), fn=funs$fn, xs=targs))
# [1] "a"
# [1] "b"
# Error: non-numeric argument to binary operator
Run Code Online (Sandbox Code Playgroud)
该targs参数必须是一个call类.call(a和b)中的变量需要是一个name类.所有这些都在下面的第二行(和第三行)中完成.?call,?as.name并且?is.language可能使这条线更容易理解.
dat <- data.frame(a=runif(10), b=runif(10), grp=rep(1:2, each=5))
targs_quoted = do.call(call, c("list", lapply(targs, as.name)), quote=TRUE)
# In hardcoded form, targs_quoted = quote(list(a, b))
dat %>%
group_by(grp) %>%
summarise_(out = interp(~do.call(fn, xs),
.values=list(fn=funs$fn, xs=targs_quoted)))
# Source: local data frame [2 x 2]
#
# grp out
# (int) (dbl)
# 1 1 1.0754497
# 2 2 0.9892201
Run Code Online (Sandbox Code Playgroud)
dplyr这里的"nse"(非标准评估)小插图非常有帮助.我发现.总是提到整个表,而不是分组表.这就是为什么评论中的一些建议没有按照需要"起作用"的原因.