R 拆分“…”参数并分配到多个函数
使用下面的函数R 拆分“…”参数并分配到多个函数,r,R,使用下面的函数foo()作为一个简单的例子,如果可能的话,我想将中给出的值分配到两个不同的函数中 foo <- function(x, y, ...) { list(sum = sum(x, ...), grep = grep("abc", y, ...)) } 参数似乎是先发送到grep()的。对吗?我认为R会首先看到并计算sum(),然后返回一个错误 此外,在尝试拆分…中的参数时,我遇到了麻烦sum()的形式参数为NULL,因为它是原语,因此无法使用 names(formal
foo()
作为一个简单的例子,如果可能的话,我想将中给出的值分配到两个不同的函数中
foo <- function(x, y, ...) {
list(sum = sum(x, ...), grep = grep("abc", y, ...))
}
参数似乎是先发送到grep()
的。对吗?我认为R会首先看到并计算sum()
,然后返回一个错误
此外,在尝试拆分…
中的参数时,我遇到了麻烦sum()
的形式参数为NULL
,因为它是原语,因此无法使用
names(formals(sum)) %in% names(list(...))
我也不想假设
names(formals(grep)) %in% names(list(...))
将自动传递给sum()
如何安全有效地将..
参数分配给多个函数,以便不进行不必要的计算?
从长远来看,我希望能够将此应用于具有一长串..
参数的函数,类似于download.file()
和scan()
的函数
为什么grep
在sum
之前出错
请注意,sum
对其参数更为适应:
X <- c(1:5, NA, 6:10)
sum(X, na.rm = TRUE, value = TRUE)
## [1] 56
如何将…
拆分为不同的函数
一种方法(很容易出错)是查找目标函数的参数。例如:
foo <- function(x, y, ...){
argnames <- names(list(...))
sumargs <- intersect(argnames, names(as.list(args(sum))))
grepargs <- intersect(argnames, names(as.list(args(grep))))
list(sum = do.call(sum, c(list(x), list(...)[sumargs])),
grep = do.call(grep, c(list("abc", y), list(...)[grepargs])))
}
在这种情况下,您可以替换适当的S3函数。因此,我没有一个通用的解决方案(尽管我不知道它是否存在)
如果另一个函数包含传递给..
的所有命名参数,或者该函数本身具有..
参数,则只能将..
参数传递给另一个函数。因此,对于sum
,这没有问题(args(sum)
返回函数(…,na.rm=FALSE)
)。另一方面,grep
既没有na.rm
也没有..
作为参数
args(grep)
# function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,
# fixed = FALSE, useBytes = FALSE, invert = FALSE)
这不包括…
,也不包括命名参数na.rm
。一个简单的解决方案是只定义自己的函数mygrep
,如下所示:
mygrep <- function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,
fixed = FALSE, useBytes = FALSE, invert = FALSE, ...)
grep(pattern, x, ignore.case, perl, value, fixed, useBytes, invert)
mygrep独立列表如果您真的想将不同的参数集传递给不同的函数,那么指定独立列表可能更为简洁:
foo <- function(x, y, sum = list(), grep = list()) {
list(sum = do.call("sum", c(x, sum)), grep = do.call("grep", c("abc", y, grep)))
}
# test
X <- c(1:5, NA, 6:10)
Y <- "xyzabcxyz"
foo(X, Y, sum = list(na.rm = TRUE), grep = list(value = TRUE))
## $sum
## [1] 55
##
## $grep
## [1] "xyzabcxyz"
ii)nls
也使用..
和控件
列表采用这种方法:
> args(mapply)
function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
NULL
> args(nls)
function (formula, data = parent.frame(), start, control = nls.control(),
algorithm = c("default", "plinear", "port"), trace = FALSE,
subset, weights, na.action, model = FALSE, lower = -Inf,
upper = Inf, ...)
NULL
将完全相同的…
值发送到两个函数sum(X,na.rm=TRUE,value=TRUE)
不会返回错误(注意sum(1,na.rm=TRUE,value=TRUE)==2
),但是grep(“abc”,Y,na.rm=TRUE,value=TRUE)
会根据函数实际使用的内容更改…
。如果你想分割参数,你必须自己做。另一种方法是为所有非常用参数提供默认值。一般来说,尝试将省略号args发送到多个地方会导致悲伤。我认为一种更干净、更健壮的方法是避免…
对所有内部函数或其中一个内部函数以外的所有函数使用do.call
foo=function(x,y,sum_args=list(NULL),grep_args=list(NULL))list(sum=do.call(“sum”,c(list(x),sum_args)),grep=do.call(“grep”,c(list(“abc”),list(y),grep_args))
<代码>foo(c(1:5,NA,6:10),“xyzabcxyz”)
foo(c(1:5,NA,6:10),“xyzabcxyz”,sum_args=list(NA.rm=TRUE),grep_args=list(value=TRUE))
@alexis_laz是的,我说的是:-)。非常详细。对于基本函数,您可以使用例如formals(args(sum))
来检索参数。第一句话不对-您可以传递…
,即使其他函数不接受…
。例如:add@wch:感谢您指出这一点。相应地修改了第一句。第一段仍然具有误导性
foo <- function(x, y, ...){
list(sum = sum(x, ...), grep = mygrep("abc", y, ...))
}
X <- c(1:5, NA, 6:10)
Y <- "xyzabcxyz"
foo(X, Y, na.rm = TRUE, value = TRUE)
# $sum
# [1] 56
#
# $grep
# [1] "xyzabcxyz"
foo <- function(x, y, sum = list(), grep = list()) {
list(sum = do.call("sum", c(x, sum)), grep = do.call("grep", c("abc", y, grep)))
}
# test
X <- c(1:5, NA, 6:10)
Y <- "xyzabcxyz"
foo(X, Y, sum = list(na.rm = TRUE), grep = list(value = TRUE))
## $sum
## [1] 55
##
## $grep
## [1] "xyzabcxyz"
foo <- function(x, y, sum = list(), ...) {
list(sum = do.call("sum", c(x, sum)), grep = grep("abc", y, ...))
}
foo(X, Y, sum = list(na.rm = TRUE), value = TRUE)
> args(mapply)
function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
NULL
> args(nls)
function (formula, data = parent.frame(), start, control = nls.control(),
algorithm = c("default", "plinear", "port"), trace = FALSE,
subset, weights, na.action, model = FALSE, lower = -Inf,
upper = Inf, ...)
NULL