R – Default argument in R function (formal argument matched by multiple actual arguments)

argument-passing, function, r

Simple question, I hope. I want to write a plotting function that has a default value for the y-axis label if the user doesn't specify. I'd also like to allow the ... argument for other plotting parameters, and allow the user to set ylab manually. But I can't figure out how to do this.

# simple scatterplot function with a default ylabscatter <- function(x,y, ...) {    plot(x, y, ylab="Default y-axis label", ...)}# generate datax <- rnorm(100)y <- x+rnorm(100)# use the defaultscatter(x,y)# here I want to use my own label, but I get an error!scatter(x, y, ylab="New y-axis label")

The error I get is:

Error in plot.default(x, y, ylab = "Default y-axis label", ...) :   formal argument "ylab" matched by multiple actual arguments 

I understand the problem, but I don't know the best way to fix it. Thanks for the help!

EDIT: I realize I can do something like

scatter <- function(x,y,ylab = "Default y-axis label", ...) {    plot(x, y, ylab= ylab, ...)}

…but if I'm writing a package to submit to CRAN, and I have lots of default options I'd like to fiddle with, I don't want to have to document all these standard plotting arguments because they're used in my function definition.

Best Solution

Try doing this instead:

scatter <- function(x,y,ylab = "Default y-axis label", ...) {    plot(x, y, ylab= ylab, ...)}

Expanding slightly on Arun's answer, this is a sketch of one route to take if you have many arguments:

def_args <- list(ylab = "Default Label",xlab = "Default Label")scatter <- function(x,y, ...) {    cl <- as.list(match.call())[-1L]    do.call("plot",c(cl,def_args[!names(def_args) %in% names(cl)]))}

Some thought would be needed to decide how you want to handle partial matching of arguments (if at all). e.g. perhaps something like this:

scatter <- function(x,y, ...) {    cl <- as.list(match.call())[-1L]    names(cl) <- match.arg(names(cl),                           names(formals(plot.default)),several.ok = TRUE)    do.call("plot",c(cl,def_args[!names(def_args) %in% names(cl)]))}

would handle partial matching of arguments.