Reputation: 99331
Consider the following function foo
. I'd like to hard-code na.rm = TRUE
into each of the calls in the list that returns the result, but I only want to write it once. My current implementation does not work.
foo <- function(x) {
e <- expression(na.rm = TRUE)
list(sum(x, eval(e)), mean(x, eval(e)), sd(x, eval(e)))
}
I do not want to use ...
in the argument list for this function. I don't want to give the user the option to add an na.rm
argument. The problem with the above code is that
> eval(expression(na.rm = TRUE))
# [1] TRUE
and therefore the TRUE
is passed to the trim
argument in mean
, instead of na.rm
> foo(c(1, NA, 3))
# Error in mean.default(x, eval(e)) : 'trim' must be numeric of length one
Is there a way to pass the argument as an expression, perhaps with quote
or substitute
, so that R would read the argument as na.rm = TRUE
instead of just TRUE
?
Note: My actual function is using quiet = TRUE
five times in seven lines, so the code would be cleaner if I could just write the expression once, and pass it to each of the five functions.
Upvotes: 3
Views: 95
Reputation: 108523
I don't really know whether this is a good idea in any case, but what you want to do can be done with 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)
)
}
As Hadley said in the comments, you don't want to copy x
completely in the list args
, as that can give memory problems when x
is big. Hence the use of quote()
(thx Hadley)
This gives:
> foo(c(1, NA, 3))
[[1]]
[1] 4
[[2]]
[1] 2
[[3]]
[1] 1.414214
Upvotes: 4
Reputation: 887048
You could try:
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
Upvotes: 3
Reputation: 81683
You can exclude the NA
s before using the functions:
foo <- function(x) {
x2 <- na.omit(x)
list(sum(x2), mean(x2), sd(x2))
}
Another possibility is to use lapply
with the functions you want to use:
foo <- function(x) {
lapply(c(sum, mean, sd), function(f) f(x, na.rm = TRUE))
}
Upvotes: 3