How to run a function multiple times and write the results to a list?
Asked Answered
D

3

14

I have a function that creates a matrix and I want to call this function a thousand times such that in the end I have a list of 1000 matrices. Here is an example:

set.seed(1)
gen_mat <- function(x) matrix(c(1, 1, 1, x + rnorm(1)), nrow = 2)

Now, I tried replicate(10, gen_mat(1)), but this returns an array and not a list. How to do it?

Dietz answered 7/9, 2017 at 19:59 Comment(1)
Look at the documentation for ?replicate: replicate(10, gen_mat(1), simplify=FALSE)Bayly
P
17

Combination of above answer, comment, and my own answer. Naturally, I like mine better. Also, I think there is a mistake in the above answer for base R.

n <- 10

# give 1 to gen_mat n-times
lapply(rep(1, n), gen_mat)

# replicate n-times 
replicate(n, gen_mat(1), simplify=FALSE)

# lapply returns error if FUN is not function or 
# the function is not taking an argument. Hence a dummy function.
lapply(seq_len(n), function(x) gen_mat(1))

microbenchmarking the three methods

I used a larger value for n, but the results are similar in my desktop with smaller n as well. For this, replicate takes longer than the other two methods.

set.seed(1)
gen_mat <- function(x) matrix(c(1, 1, 1, x + rnorm(1)), nrow = 2)
n <- 1000 

library(microbenchmark)
library(ggplot2)

mb <- microbenchmark(
  lap1 = {lapply(rep(1, n), gen_mat)},
  repl = {replicate(n, gen_mat(1), simplify=FALSE)},
  lap2 = {lapply(seq_len(n), function(x) gen_mat(1))},
  times = 10000L
)

mb
# Unit: milliseconds
# expr      min       lq     mean   median       uq      max neval cld
# lap1 2.839435 3.494157 4.806954 3.854269 5.611413 103.0111 10000  a 
# repl 3.091829 3.777199 5.140789 4.165856 6.013591 101.4318 10000   b
# lap2 3.131491 3.761274 5.089170 4.140316 5.939075 101.1983 10000   b

autoplot(mb)

enter image description here

Placable answered 14/2, 2018 at 13:52 Comment(2)
replicate is usually the fastest option.Diaspore
That could be the case. But, in this case, the lapplys are doing better than the replicate, as per benchmarking shown above now.Placable
C
5

base R

n <- 10
lapply(seq_len(n), gen_mat(1))

purrr package

library(purrr)
map(seq_len(n), ~gen_mat(1))
Chev answered 7/9, 2017 at 20:3 Comment(0)
O
2

Just adding purrr::rerun is shorthand for replicate(..., simplify = FALSE)

library(purrr)
rerun(10, gen_mat(1))

# [[1]]
#      [,1]     [,2]
# [1,]    1 1.000000
# [2,]    1 1.918977

# [[2]]
#      [,1]     [,2]
# [1,]    1 1.000000
# [2,]    1 1.782136

# [[3]]
#      [,1]     [,2]
# [1,]    1 1.000000
# [2,]    1 1.074565

# [[4]]
#      [,1]       [,2]
# [1,]    1  1.0000000
# [2,]    1 -0.9893517

# [[5]]
#      [,1]     [,2]
# [1,]    1 1.000000
# [2,]    1 1.619826

# [[6]]
#      [,1]      [,2]
# [1,]    1 1.0000000
# [2,]    1 0.9438713

# [[7]]
#      [,1]      [,2]
# [1,]    1 1.0000000
# [2,]    1 0.8442045

# [[8]]
#      [,1]       [,2]
# [1,]    1  1.0000000
# [2,]    1 -0.4707524

# [[9]]
#      [,1]      [,2]
# [1,]    1 1.0000000
# [2,]    1 0.5218499

# [[10]]
#      [,1]     [,2]
# [1,]    1 1.000000
# [2,]    1 1.417942
Ortego answered 9/4, 2020 at 9:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.