简体   繁体   English

R函数使用函数作为参数,每个函数都带有可变参数

[英]R function with functions as arguments, each with variable arguments

In answer to a question on Cross Validated , I wrote a simple function that used arbitrary quantile functions as its arguments 在回答关于Cross Validated的问题时 ,我写了一个简单的函数 ,它使用任意分位数函数作为其参数

etacor=function(rho=0,nsim=1e4,fx=qnorm,fy=qnorm){
  #generate a bivariate correlated normal sample
  x1=rnorm(nsim);x2=rnorm(nsim)
  if (length(rho)==1){
    y=pnorm(cbind(x1,rho*x1+sqrt((1-rho^2))*x2))
    return(cor(fx(y[,1]),fy(y[,2])))
    }
  coeur=rho
  rho2=sqrt(1-rho^2)
  for (t in 1:length(rho)){
     y=pnorm(cbind(x1,rho[t]*x1+rho2[t]*x2))
     coeur[t]=cor(fx(y[,1]),fy(y[,2]))}
  return(coeur)
  }

However, both fx and fy may require their own parameters. 但是, fxfy可能需要自己的参数。 For instance, when fx=qchisq or when fy=qgamma . 例如,当fx=qchisqfy=qgamma As a default solution, in my implementation, I used 作为默认解决方案,在我的实现中,我使用过

fx=function(x) qchisq(x,df=3)

and

fy=function(x) qgamma(x,scale=.2)

but this is quite time consuming. 但这非常耗时。

For instance, 例如,

> rhos=seq(-1,1,.01)
> system.time(trancor<-etacor(rho=rhos,fx=qlnorm,fy=qexp))
utilisateur     système      écoulé 
      0.834       0.001       0.834 

versus

> system.time(trancor<-etacor(rho=rhos,fx=qlnorm,fy=function(x) qchisq(x,df=3)))
utilisateur     système      écoulé 
      8.673       0.006       8.675 

An illustration of my comment above: 以上评论的说明:

etacor1 <- function(rho = 0,
                    nsim = 1e4,
                    fx = qnorm,
                    fy = qnorm,
                    fx.args = formals(fx),
                    fy.args = formals(fy)){
    #generate a bivariate correlated normal sample
    x1 <- rnorm(nsim)
    x2 <- rnorm(nsim)

    fx.arg1 <- names(formals(fx))[1]
    fy.arg1 <- names(formals(fy))[1]

    if (length(rho) == 1){
        y <- pnorm(cbind(x1, rho * x1 + sqrt((1 - rho^2)) * x2))
        fx.args[[fx.arg1]] <- y[,1]
        fy.args[[fy.arg1]] <- y[,2]
        return(cor(do.call(fx,as.list(fx.args)),
                   do.call(fy,as.list(fy.args))))
    }

    coeur <- rho
    rho2 <- sqrt(1 - rho^2)

    for (t in 1:length(rho)){
        y <- pnorm(cbind(x1,rho[t]*x1+rho2[t]*x2))
        fx.args[[fx.arg1]] <- y[,1]
        fy.args[[fy.arg1]] <- y[,2]
        coeur[t] <- cor(do.call(fx,as.list(fx.args)),
                        do.call(fy,as.list(fy.args)))
    }

    return(coeur)
}

I am displeased with the apparent necessity of as.list . 我对as.list的明显必要性感到不满。 I feel like I should know why that is, but it is escaping me at the moment. 我觉得我应该知道为什么会这样,但此刻它正在逃避我。

In using this function, it should not be necessary to pass in all arguments, but you do need to make sure any list you pass to fx.args or fy.args is named. 在使用此函数时,不必传入所有参数,但您需要确保传递给fx.argsfy.args任何列表fy.args命名。

Thanks for the comments and answer! 感谢您的评论和回答! I fear the core issue is that, as pointed out by joran and Mr Flick , some quantile functions are much slower to execute than others: 我担心核心问题是,正如joranFlick先生所指出的,一些分位数函数的执行速度比其他函数慢得多:

> system.time(etacor(rhos,fx=function(x) qexp(x)))
utilisateur     système      écoulé 
      1.182       0.000       1.182 
> system.time(etacor(rhos,fx=qexp))
utilisateur     système      écoulé 
      1.238       0.000       1.239 

versus

> system.time(etacor(rhos,fx=function(x) qchisq(x,df=3)))
utilisateur     système      écoulé 
      4.955       0.000       4.951 
> system.time(etacor(rhos,fx=function(x) qgamma(x,sha=.3)))
utilisateur     système      écoulé 
      4.316       0.000       4.314 

So in the end using the definition of the function when it requires parameters does seem as a straightforward and easy solution. 所以最后在需要参数时使用函数的定义似乎是一个简单易行的解决方案。 Thanks for all of your inputs. 感谢您的所有投入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM