将带有“...”的可选参数传递给多个函数;控制参数匹配?

Passing optional arguments with `...` to multiple functions; control argument matching?

我正在尝试编写一个调用一堆子函数的父函数,这些子函数都具有非常合理的默认值并且有据可查。基于一个参数的值,我想将可能不同的参数传递给不同的子函数以进行自定义。有没有办法使用省略号或 ?

将参数传递给多个函数

这是一个简单的例子;这里的挑战是能够在用户需要时传递 na.rm and/or base,否则使用现有的默认值:

dat <- c(NA, 1:5)
# I want a flexible function that uses sensible defaults unless otherwise specified
meanLog<-function(x, ...){
  y <- log(x, ...)
  z <- mean(y, ...)
  return(z)
}

# I know I can pass ... to one function wrapped inside this one. 
justLog <- function(x, ...){
  log(x, ...)
}

justLog(dat)
justLog(dat, base = 2)

# or another
justMean <- function(x, ...){
  mean(x, ...)
}

justMean(dat)
justMean(dat, na.rm =T)


# but I can't pass both arguments
meanLog(dat) # works fine, but I want to customize a few things
meanLog(dat, na.rm =T, base = 2)

justMean(dat, base =2)
# In this case that is because justLog breaks if it gets an unused na.rm 
justLog(dat, na.rm =T)

1) 定义 do.call2 类似于 do.call 除了它接受未命名参数以及字符向量中的命名参数 accepted 默认为函数中的形式。

请注意,mean 的参数不包括 na.rm——它被 dot dot dot 参数吞噬了——但 mean.default 方法包含。原始函数也没有形式,因此必须明确指定 accepted 参数而不是默认参数。

do.call2 <- function(what, args, accepted = formalArgs(what)) {
  ok <- names(args) %in% c("", accepted)
  do.call(what, args[ok])
}

# test

dat <- c(NA, 1:5)
meanLog <- function(x, ...){
  y <- do.call2("log", list(x, ...), "base")
  z <- do.call2("mean.default", list(y, ...))
  return(z)
}

meanLog(dat, na.rm = TRUE, base = 2)
## [1] 1.381378

# check

mean(log(dat, base = 2), na.rm = TRUE)
## [1] 1.381378

2)另一种可能性是为均值和对数提供单独的参数。

(一种变体是对其中一个函数使用点点点,对其他函数使用参数列表。例如 nls 在 R 中使用点点点但也使用 control参数指定其他参数。)

# test

dat <- c(NA, 1:5)
meanLog <- function(x, logArgs = list(), meanArgs = list()) {
  y <- do.call("log", c(list(x), logArgs))
  z <- do.call("mean", c(list(y), meanArgs))
  return(z)
}

meanLog(dat, logArgs = list(base = 2), meanArgs = list(na.rm = TRUE))
## [1] 1.381378

# check

mean(log(dat, base = 2), na.rm = TRUE)
## [1] 1.381378