我大量使用'do.call'来生成函数调用.例如:
myfun <- "rnorm";
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);
Run Code Online (Sandbox Code Playgroud)
但是,有时我想从某个包中明确调用一个函数.与例如类似stats::rnorm(n=10, mean=5).有没有什么方法可以使用do.call,或者创建一个与do.call类似的函数来使其工作:
myfun <- "stats::rnorm";
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);
Run Code Online (Sandbox Code Playgroud)
Tom*_*mmy 20
没有名为"stats :: rnorm"的函数.您必须rnorm在"stats"命名空间中找到该函数:
myfun <- get("rnorm", asNamespace("stats"))
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);
Run Code Online (Sandbox Code Playgroud)
现在你当然也可以从"stats :: rnorm"这样的名称开始,并将其拆分为命名空间部分和函数名称:
funname <- "stats::rnorm"
fn <- strsplit(funname, "::")[[1]]
myfun <- if (length(fn)==1) fn[[1]] else get(fn[[2]], asNamespace(fn[[1]]))
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);
Run Code Online (Sandbox Code Playgroud)
更新我只想表明这种方法比@Jeroen快2.5倍...
do.call.tommy <- function(what, args, ...) {
if(is.character(what)){
fn <- strsplit(what, "::")[[1]]
what <- if(length(fn)==1) {
get(fn[[1]], envir=parent.frame(), mode="function")
} else {
get(fn[[2]], envir=asNamespace(fn[[1]]), mode="function")
}
}
do.call(what, as.list(args), ...)
}
# Test it
do.call.tommy(runif, 10)
f1 <- function(FUN) do.call.tommy(FUN, list(5))
f2 <- function() { myfun<-function(x) x; do.call.tommy(myfun, list(5)) }
f1(runif)
f1("stats::runif")
f2()
# Test the performance...
system.time(for(i in 1:1e4) do.call.jeroen("stats::runif", list(n=1, max=50))) # 1.07 secs
system.time(for(i in 1:1e4) do.call.tommy("stats::runif", list(n=1, max=50))) # 0.42 secs
Run Code Online (Sandbox Code Playgroud)
Vin*_*ynd 16
您可以删除引号:这将是函数本身,而不是其名称.
myfun <- stats::rnorm
myargs <- list(n=10, mean=5)
do.call(myfun, myargs)
Run Code Online (Sandbox Code Playgroud)