将带有“...”的可选参数传递给多个函数;控制参数匹配?
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
我正在尝试编写一个调用一堆子函数的父函数,这些子函数都具有非常合理的默认值并且有据可查。基于一个参数的值,我想将可能不同的参数传递给不同的子函数以进行自定义。有没有办法使用省略号或
这是一个简单的例子;这里的挑战是能够在用户需要时传递 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