将未评估的参数替换为多个函数

时间:2014-08-29 08:13:36

标签: r

考虑以下函数foo。我想将na.rm = TRUE硬编码到列表中返回结果的每个调用中,但我只想写一次。我当前的实现不起作用。

foo <- function(x) {
    e <- expression(na.rm = TRUE)
    list(sum(x, eval(e)), mean(x, eval(e)), sd(x, eval(e)))
}

想在此函数的参数列表中使用...。我不想让用户选择添加na.rm参数。上面代码的问题是

> eval(expression(na.rm = TRUE))
# [1] TRUE

因此TRUE传递给trim中的mean参数,而不是na.rm

> foo(c(1, NA, 3))
# Error in mean.default(x, eval(e)) : 'trim' must be numeric of length one

有没有办法将参数作为表达式传递,可能使用quotesubstitute,以便R将参数读为na.rm = TRUE而不只是TRUE

注意:我的实际功能是在七行中使用quiet = TRUE五次,所以如果我只能编写一次表达式,并将其传递给每个代码,代码就会更清晰五个功能。

3 个答案:

答案 0 :(得分:4)

在任何情况下,我都不知道这是否是一个好主意,但您可以使用do.call完成您想要做的事情:

foo <- function(x) {
  args <- list(quote(x),na.rm=TRUE)
  list(
    do.call(sum,args), 
    do.call(mean, args),
    do.call(sd, args)
  )
}

正如哈德利在评论中所说,你不想完全在列表x中复制args,因为当x很大时,这可能会导致内存问题。因此使用quote()(thx Hadley)

这给出了:

> foo(c(1, NA, 3))
[[1]]
[1] 4

[[2]]
[1] 2

[[3]]
[1] 1.414214

答案 1 :(得分:3)

您可以在使用这些功能之前排除NA

foo <- function(x) {
    x2 <- na.omit(x)
    list(sum(x2), mean(x2), sd(x2))
}

另一种可能性是将lapply与您要使用的功能一起使用:

foo <- function(x) {
   lapply(c(sum, mean, sd), function(f) f(x, na.rm = TRUE))
}

答案 2 :(得分:3)

你可以尝试:

fun1 <- function(x) {
    lapply(c(sum, mean, sd), do.call, list(x, na.rm=TRUE))
}

fun1(c(1,NA,3))
#[[1]]
#[1] 4

#[[2]]
#[1] 2

#[[3]]
#[1] 1.414214