簡體   English   中英

R函數使用函數作為參數,每個函數都帶有可變參數

[英]R function with functions as arguments, each with variable 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)
  }

但是, fxfy可能需要自己的參數。 例如,當fx=qchisqfy=qgamma 作為默認解決方案,在我的實現中,我使用過

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

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

但這非常耗時。

例如,

> 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 

> 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 

以上評論的說明:

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)
}

我對as.list的明顯必要性感到不滿。 我覺得我應該知道為什么會這樣,但此刻它正在逃避我。

在使用此函數時,不必傳入所有參數,但您需要確保傳遞給fx.argsfy.args任何列表fy.args命名。

感謝您的評論和回答! 我擔心核心問題是,正如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 

> 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 

所以最后在需要參數時使用函數的定義似乎是一個簡單易行的解決方案。 感謝您的所有投入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM