Search code examples
rellipsis

Remove an argument / element from ellipsis


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

Solution

  • 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.