Search code examples
rfor-loopapplydo.call

Use array of variables as iterative inputs to R function without for loop


I am trying to use an array to feed all the variables into a function, K times. Here is a simple example:

set.seed(707)

Func<-function(a,b,c,d,e,f,g,h,i,j){
  temp <- a+b+c+d+e+f+g+h+i+j
  return(temp)
}

K <- 3
library(lhs)
A <- randomLHS(10,K)

> A
            [,1]       [,2]      [,3]
 [1,] 0.71223229 0.62418246 0.3933959
 [2,] 0.01531924 0.06501699 0.7463748
 [3,] 0.85278795 0.19983286 0.1856308
 [4,] 0.28234183 0.32716120 0.6706615
 [5,] 0.11708063 0.74196491 0.8515147
 [6,] 0.33521099 0.45473874 0.9173855
 [7,] 0.97812812 0.57400252 0.4987922
 [8,] 0.53003009 0.94340463 0.0293076
 [9,] 0.49162910 0.84928499 0.2309974
[10,] 0.69963290 0.26794110 0.5024444

I'd like to feed each column to the function Func iteratively, and then combine the results. The best solution I can come up with relies on a for loop and indexing, but I am wondering if there is a better way to do this with apply:

Out <- NULL
for(i in 1:K){
test <- do.call(what = Func, args = as.list(A[,i]))
Out <- c(Out,test)
}

To make sure it worked as I think it should, I just compare:

Out
colSums(A)

> Out
[1] 5.014393 5.047530 5.026505
> colSums(A)
[1] 5.014393 5.047530 5.026505

Solution

  • With apply():

    Out <- apply(A, 2, FUN = \(x) do.call(Func, args = as.list(x)))
    

    And some performance benchmarks:

    microbenchmark::microbenchmark(
    loop = {
    Out <- NULL
    for(i in 1:K){
      test <- do.call(what = Func, args = as.list(A[,i]))
      Out <- c(Out,test)
    }
    },
    apply = {Out <- apply(A, 2, FUN = \(x) do.call(Func, args = as.list(x)))}
    )
    #Unit: microseconds
    #  expr    min      lq     mean median      uq     max neval
    #  loop 2465.3 2522.10 2833.954 2625.7 2797.00 13389.8   100
    # apply   35.7   39.75   64.778   48.7   53.65  1657.5   100