R函数中的默认参数(形式参数由多个实际参数匹配)

时间:2014-05-28 21:25:12

标签: r function argument-passing

简单的问题,我希望。我想编写一个绘图函数,如果用户没有指定,则该函数具有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 

我理解这个问题,但我不知道解决问题的最佳方法。谢谢你的帮助!

编辑:我意识到我可以做类似

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

...但是如果我正在写一个包提交给CRAN,并且我有很多默认选项我想摆弄,我不想要记录所有这些标准绘图参数因为它们在我的函数定义中使用。

3 个答案:

答案 0 :(得分:10)

尝试这样做:

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

稍微扩展一下Arun的答案,如果你有很多论点,这是一条路线的草图:

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

将处理参数的部分匹配。

答案 1 :(得分:5)

使用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%进行部分参数匹配。

答案 2 :(得分:3)

我使用函数来构建参数列表。在我的情况下,我不关心部分匹配参数名称,这很好,因为它不支持它。

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