作者:不言不语都可以温柔_631 | 来源:互联网 | 2023-05-18 22:14
Usingthefollowingfunctionfoo()asasimpleexample,Idliketodistributethevaluesgivenin.
Using the following function foo()
as a simple example, I'd like to distribute the values given in ...
two different functions, if possible.
使用以下函数foo()作为一个简单的例子,如果可能的话,我想分发两个不同函数中给出的值。
foo <- function(x, y, ...) {
list(sum = sum(x, ...), grep = grep("abc", y, ...))
}
In the following example, I would like na.rm
to be passed to sum()
, and value
to be passed to grep()
. But I get an error for an unused argument in grep()
.
在下面的示例中,我希望将na.rm传递给sum(),并将值传递给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)
It seems like the arguments were sent to grep()
first. Is that correct? I would think R would see and evaluate sum()
first, and return an error for that case.
似乎首先将参数发送给grep()。那是对的吗?我认为R会首先看到并评估sum(),并为该情况返回一个错误。
Furthermore, when trying to split up the arguments in ...
, I ran into trouble. sum()
's formal arguments are NULL
because it is a .Primitive
, and therefore I cannot use
此外,当试图将论点分开......时,我遇到了麻烦。 sum()的形式参数是NULL,因为它是.Primitive,因此我无法使用
names(formals(sum)) %in% names(list(...))
I also don't want to assume that the leftover arguments from
我也不想假设剩下的论据来自
names(formals(grep)) %in% names(list(...))
are to automatically be passed to sum()
.
将自动传递给sum()。
How can I safely and efficiently distribute ...
arguments to multiple functions so that no unnecessary evaluations are made?
如何安全有效地将...参数分配给多个函数,以便不进行不必要的评估?
In the long-run, I'd like to be able to apply this to functions with a long list of ...
arguments, similar to those of download.file()
and scan()
.
从长远来看,我希望能够将它应用于具有一长串...参数的函数,类似于download.file()和scan()。
3 个解决方案
23
Separate Lists If you really want to pass different sets of parameters to different functions then it's probably cleaner to specify separate lists:
单独的列表如果您确实想要将不同的参数集传递给不同的函数,那么指定单独的列表可能更简洁:
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"
Hybrid list / ... An alternative is that we could use ... for one of these and then specify the other as a list, particularly in the case that one of them is frequently used and the other is infrequently used. The frequently used one would be passed via ... and the infrequently used via a list. e.g.
混合列表/ ...另一种选择是我们可以使用...作为其中之一,然后将另一个指定为列表,特别是在经常使用其中一个而另一个不经常使用的情况下。经常使用的一个将通过...传递,并且通过列表不经常使用。例如
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)
Here are a couple of examples of the hybrid approach from R itself:
以下是R本身的混合方法的几个例子:
i) The mapply
function takes that approach using both ...
and a MoreArgs
list:
i)mapply函数使用...和MoreArgs列表的方法:
> args(mapply)
function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
NULL
ii) nls
also takes this approach using both ...
and the control
list:
ii)nls也使用这两种方法和控制列表:
> 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
0
You can only pass the ...
argument to another function, if that other function includes all named arguments that you pass to ...
or if it has a ...
argument itself. So for sum
, this is no problem (args(sum)
returns function (..., na.rm = FALSE)
). On the other hand grep
has neither na.rm
nor ...
as an argument.
您只能将...参数传递给另一个函数,如果该其他函数包含您传递给的所有命名参数...或者它本身具有...参数。所以总和来说,这没有问题(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)
This does not include ...
and also does not include a named argument na.rm
either. A simple solution is to just define your own function mygrep
as follows:
这不包括......也不包括命名参数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)
Then it seems to work:
然后它似乎工作:
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"