Question

I have defined a custom function, like this:

my.fun = function() {

      for (i in 1:1000) {
      ...
        for (j in 1:20) {
          ...
        }
      }

 return(output)

}

which returns an output matrix, output, composed by 1000 rows and 20 columns.

What I need to do is to repeat the function say 5 times and to store the five output results into a brand new matrix, say final, but without using another for-loop (this for making the code clearer, and also because in a second moment I would like to try to parallelize these additional 5 repetitions).

Hence final should be a matrix with 5000 rows and 20 columns (the rationale behind these 5 repetitions is that within the two for-loops I use, among other functions, sample).

I tried to use final <- replicate(5, my.fun()), which correctly computes the five replications, but then I have to "manually" put the elements into a brand new 5000 x 20 matrix.. is there a more elgant way to do so? (maybe using sapply()?). Many thanks

Was it helpful?

Solution

As is stands you probably have an array with three dimensions. If you wanted to have a list you would have added simplify=FALSE. Try this:

do.call( rbind, replicate(5, my.fun(), simplify=FALSE ) )

Or you can use aperm in the case where "final" is still an array:

fun <- function() matrix(1:10, 2,5)
final <- replicate( 2, fun() )
> final
, , 1

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

, , 2

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

> t( matrix(aperm(final, c(2,1,3)), 5,4) )
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
[3,]    1    3    5    7    9
[4,]    2    4    6    8   10

There may be more economical matrix operations. I just haven't discovered one yet.

OTHER TIPS

If you replace replicate with rlply from the plyr package, you can use do.call with rbind:

library(plyr)
do.call(rbind, rlply(5, my.fun()))

If you'd rather not rely on the plyr package, you can always do:

do.call(rbind, lapply(1:5, function(i) my.fun()))

Depends on which package you use for parallel computing, but here's how I would do it (hide it in a loop using sapply, just like replicate).

library(snowfall)
sfInit(parallel = TRUE, cpus = 4, type = "SOCK")
# sfExport() #export appropriate objects that will be needed inside a function, if applicable
# sfLibrary() #call to any special library
out <- sfSapply(1:5, fun = my.fun, simplify = FALSE)
sfStop()

Try this:

final <- replicate(5, my.fun(), simplify = "matrix")

You will get the result of 'final' in the form of matrix.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top