# R with functions as arguments, each with variable arguments

In response to the Cross Validated question, I wrote a simple function that used arbitrary quantile functions as its arguments

``````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, `fx`

and `fy`

may require your own parameters. For example, when `fx=qchisq`

or when `fy=qgamma`

. As the default solution in my implementation, I used

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

and

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

but it takes a long time.

For example,

``````> 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
```

```

against

``````> 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
```

```
+3

source to share

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))
fy.arg1 <- names(formals(fy))

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 unhappy with the obvious need `as.list`

. I feel like I should know why this is so, but now it is eluding me.

When using this function, it is not necessary to pass all the arguments, but you do need to make sure that the list you pass to `fx.args`

or `fy.args`

is named.

+3

source

Thanks for the comments and response! I'm afraid the main problem is that, as pointed out by joran and Mr Flick , some quantile functions are much slower than others:

``````> 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
```

```

against

``````> 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 a function definition when it requires parameters seems like a simple and easy solution. Thanks for all your inputs.

+1

source

All Articles