使用以下函数foo()作为一个简单的例子...,如果可能的话,我想分发两个不同函数给出的值.
foo <- function(x, y, ...) {
list(sum = sum(x, ...), grep = grep("abc", y, ...))
}
Run Code Online (Sandbox Code Playgroud)
在下面的例子中,我希望na.rm传递给sum(),并value传递给grep().但是我在一个未使用的参数中得到一个错误grep().
X <- c(1:5, NA, 6:10)
Y <- "xyzabcxyz"
foo(X, Y, na.rm = TRUE, value = TRUE)
# Error in grep("abc", y, ...) : unused argument (na.rm = TRUE)
Run Code Online (Sandbox Code Playgroud)
看起来这些论点grep()首先被发送出去了.那是对的吗?我认为R会sum()首先看到并评估,并为该情况返回错误.
此外,当试图分裂论点时...,我遇到了麻烦. sum()正式的论据是NULL因为它是一个.Primitive,因此我无法使用
names(formals(sum)) %in% names(list(...))
Run Code Online (Sandbox Code Playgroud)
我也不想假设剩下的论据来自
names(formals(grep)) %in% names(list(...))
Run Code Online (Sandbox Code Playgroud)
是自动传递给sum().
如何安全有效地将...参数分配给多个函数,以便不进行不必要的评估?
从长远来看,我希望能够将这个应用于具有长...参数列表的函数,类似于download.file()和scan().
G. *_*eck 28
单独的列表如果您确实希望将不同的参数集传递给不同的函数,那么指定单独的列表可能更简洁:
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"
Run Code Online (Sandbox Code Playgroud)
混合列表/ ...另一种选择是我们可以使用...作为其中之一,然后将另一个指定为列表,特别是在经常使用其中一个而另一个不经常使用的情况下.经常使用的一个将通过...传递,并且通过列表不经常使用.例如
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)
Run Code Online (Sandbox Code Playgroud)
以下是R本身的混合方法的几个例子:
i)该mapply函数使用这两种方法...和MoreArgs列表:
> args(mapply)
function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
NULL
Run Code Online (Sandbox Code Playgroud)
ii)nls同时采用这种方法...和control列表:
> 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
Run Code Online (Sandbox Code Playgroud)
r2e*_*ans 14
为什么grep以前出错sum?
看到它sum更适应其论点:
X <- c(1:5, NA, 6:10)
sum(X, na.rm = TRUE, value = TRUE)
## [1] 56
Run Code Online (Sandbox Code Playgroud)
它没有失败,因为它不关心其他命名参数,所以value = TRUE简化为TRUE哪个总和为1.顺便说一下:
sum(X, na.rm = TRUE)
## [1] 55
Run Code Online (Sandbox Code Playgroud)如何拆分...到不同的功能?
一种方法(非常容易出错)是寻找目标函数的args.例如:
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])))
}
Run Code Online (Sandbox Code Playgroud)
只要函数使用的参数没有正确报告args,例如S3对象,就很容易出错.举个例子:
names(as.list(args(plot)))
## [1] "x" "y" "..." ""
names(as.list(args(plot.default)))
## [1] "x" "y" "type" "xlim" "ylim"
## [6] "log" "main" "sub" "xlab" "ylab"
## [11] "ann" "axes" "frame.plot" "panel.first" "panel.last"
## [16] "asp" "..." ""
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以替换相应的S3函数.因此,我没有一个通用的解决方案(虽然我不知道它确实存在或不存在).