Remove an argument / element from ellipsis
Asked Answered
H

1

7

I want to drop an element from an ellipsis because I want to set it manaully inside my function. The example below illustrates the point as the error is sensible given I'm passing na.rm in manually and via ellipsis. How can I remove na.rm from the ellipsis so that the error isn't thrown?

mymean <- function(x, ...){

    dots <- list(...)

    if (is.null(dots$na.rm)) {
        na_arg <- TRUE
    } else {
        na_arg <- dots$na.rm
    }

    mean(x, na.rm = na_arg, ...)

}

set.seed(10); a <- c(rnorm(20), NA)

mymean(a)
## [1] -0.06053267

mymean(a, trim = .5)
## [1] -0.08275319

mymean(a, na.rm = TRUE, trim = .1)
## Error in mean.default(x, na.rm = na_arg, ...) : 
##   formal argument "na.rm" matched by multiple actual arguments
Hemelytron answered 27/1, 2018 at 15:51 Comment(1)
My guess is match.call is involved. Have you tried that?Files
L
9

1) lm Look at the source code of lm. Following that:

mymean1 <- function(x, ...){

    mc <- match.call()
    mc[[1]] <- as.name("mean")
    if (is.null(mc$na.rm)) mc$na.rm <- TRUE
    eval(mc, parent.frame())

}

mymean1(a, na.rm = TRUE, trim = .1)
## [1] -0.01886715
mymean1(a, trim = .1)
## [1] -0.01886715

2) do.call This would also work although there is a subtle difference, namely ... gets evaluated. In this and most cases it won't matter but it might in some less usual cases.

mymean2 <- function(x, ...) {
    dots <- list(...)
    if (! "na.rm" %in% names(dots)) dots$na.rm <- TRUE
    do.call("mean", c(list(x), dots))
}
mymean2(a, na.rm = TRUE, trim = .1)
## [1] -0.01886715
mymean2(a, trim = .1)
## [1] -0.01886715

3) ordinary arg However, it would be easier to just write:

mymean3 <- function(x, na.rm = TRUE, ...) mean(x, na.rm = na.rm, ...)

mymean3(a, na.rm = TRUE, trim = .1)
## [1] -0.01886715
mymean3(a, trim = .1)
## [1] -0.01886715

This is the usual way wrappers with different defaults are written. For example see the read.csv source code.

Lazar answered 27/1, 2018 at 16:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.