首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >do.call与"::“组合使用

do.call与"::“组合使用
EN

Stack Overflow用户
提问于 2012-04-05 11:51:04
回答 3查看 2.3K关注 0票数 20

我经常使用'do.call‘来生成函数调用。例如:

代码语言:javascript
复制
myfun <- "rnorm";
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);

然而,有时我想显式地调用某个包中的函数。类似于例如stats::rnorm(n=10, mean=5)。有没有什么方法可以使用do.call,或者创建一个行为类似于do.call的函数来让它工作:

代码语言:javascript
复制
myfun <- "stats::rnorm";
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-05 11:58:25

没有名为"stats::rnorm“的函数。您必须在"stats“名称空间中找到rnorm函数:

代码语言:javascript
复制
myfun <- get("rnorm", asNamespace("stats"))
myargs <- list(n=10, mean=5);
do.call(myfun, myargs);

当然,现在您也可以使用类似"stats::rnorm“的名称,并将其拆分为名称空间部分和函数名称:

代码语言:javascript
复制
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);

更新我只是想证明这种方法比@Jeroen的方法快2.5倍……

代码语言:javascript
复制
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
票数 23
EN

Stack Overflow用户

发布于 2012-04-05 12:02:31

您可以删除引号:这将是函数本身,而不是它的名称。

代码语言:javascript
复制
myfun <- stats::rnorm
myargs <- list(n=10, mean=5)
do.call(myfun, myargs)
票数 16
EN

Stack Overflow用户

发布于 2012-04-06 07:36:53

感谢您的回复。我想我想要这样的东西:

代码语言:javascript
复制
do.call.jeroen <- function(what, args, ...){
  if(is.function(what)){
    what <- deparse(as.list(match.call())$what);
  }
  myfuncall <- parse(text=what)[[1]];
  mycall <- as.call(c(list(myfuncall), args));
  eval(mycall, ...);
}

这似乎是do.call的一个很好的泛化,这样我仍然可以传递一个字符串作为what参数,但它巧妙地模拟了stats::rnorm(n=10, mean=5)调用。

代码语言:javascript
复制
myfun1 <- "rnorm";
myfun2 <- "stats::rnorm";
myargs <- list(n=10, mean=5);
do.call.jeroen(myfun1, myargs);
do.call.jeroen(myfun2, myargs);
do.call.jeroen(rnorm, myargs);
do.call.jeroen(stats::rnorm, myargs);

这样做的一个好处是,如果我调用的函数使用match.call()将调用存储在某个地方,它将保留实际的函数名。例如:

do.call.jeroen("stats::glm",list(formula=speed~dist,data=as.name(‘cars’)

代码语言:javascript
复制
Call:  stats::glm(formula = speed ~ dist, data = cars)

Coefficients:
(Intercept)         dist  
     8.2839       0.1656  

Degrees of Freedom: 49 Total (i.e. Null);  48 Residual
Null Deviance:      1370 
Residual Deviance: 478  AIC: 260.8 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10022436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档