10

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

Stefano Lombardi
  • 1,581
  • 2
  • 22
  • 48

4 Answers4

14

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.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
7

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()))
David Robinson
  • 77,383
  • 16
  • 167
  • 187
7

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()
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
0

Try this:

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

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

Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • I thought that `simplify` can only accept `FALSE`, `TRUE` or `"array"`. The default `TRUE` returns a vector or matrix if appropriate. – Valentin_Ștefan Mar 26 '18 at 15:28