Аргумент по умолчанию в функции R (формальный аргумент, сопоставляемый несколькими фактическими аргументами)

Простой вопрос, надеюсь. Я хочу написать функцию построения графика, которая имеет значение по умолчанию для метки оси y, если пользователь не указывает. Я также хотел бы разрешить аргумент ... для других параметров построения и разрешить пользователю устанавливать ylab вручную. Но я не могу понять, как это сделать.

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

Ошибка, которую я получаю:

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

Я понимаю проблему, но я не знаю, как ее исправить. Спасибо за помощь!

EDIT: Я понимаю, что могу сделать что-то вроде

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

... но если я пишу пакет для отправки в CRAN, и у меня есть множество параметров по умолчанию, с которыми я бы хотел поиграть, я не хочу документировать все эти стандартные аргументы построения, потому что они 'используется в определении моей функции.

3 ответа

Попробуйте сделать это вместо:

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

Развернувшись немного на ответе Аруна, это эскиз одного маршрута, если у вас много аргументов:

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)]))
}

Некоторые мысли будут необходимы, чтобы решить, как вы хотите обрабатывать частичное согласование аргументов (если вообще). например возможно, что-то вроде этого:

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)]))
}

будет обрабатывать частичное совпадение аргументов.


Один из способов использования match.call для проверки того, был ли ylab указан в качестве аргумента:

scatter <- function(x,y, ...) {
 mcall = as.list(match.call())[-1L]
 if (!"ylab" %in% names(mcall))
 plot(x, y, ylab="Default y-axis label", ...)
 else plot(x, y, ...)
}

Как упоминалось в комментарии list(...), лучше всего получить только аргумент точек, расширенный, чем получить все формальные аргументы с помощью match.call.

Вы также можете попробовать использовать pmatch вместо %in% для частичного согласования аргументов.


Я использую функцию для создания списка аргументов. В моем случае, я не забочусь о частично совпадающих именах аргументов, что хорошо, потому что это не будет поддерживать его.

# Create a list of input arguments.
# Allow arguments to be specified multiple times, first definition wins.
# The resulting list is intended to be passed to do.call().
make.args <- function(..., PRE.ARGS=list(), POST.ARGS=list()) {
 a <- list()
 l <- c(PRE.ARGS, list(...), POST.ARGS)
 for (name in unique(names(l))) {
 a[[name]] <- l[[name]] # First occurrence will be found.
 }
 return(a)
}

Пример использования:

plot.rate <- function(col, cond=NULL, ...) {
 col <- paste(col, collapse=' + ')
 f <- paste(col, '~ Rate')
 if (!is.null(cond)) {
 cond <- paste(cond, collapse=' + ')
 f <- paste(f, cond, sep='|')
 }
 arg.list <- make.args(...
 , x = as.formula(f)
 , main=col
 , grid=TRUE
 , scales=list(x=list(alternating=1) # bottom(/left)
 , y=list(alternating=3)) # both
 , xlab='x RTM'
 )
 do.call(xyplot, arg.list)
}

licensed under cc by-sa 3.0 with attribution.