Here's a benchmark test of the different strategies that were suggested. Feel free to update if you have new ideas / strategies.
# packages
require(data.table)
require(tidyr)
require(microbenchmark)
# data
lst <- replicate(100, matrix(rnorm(16), ncol = 4), simplify = FALSE)
# benchmark test
microbenchmark(
do.call(rbind, lst),
Reduce(rbind, lst),
apply(simplify2array(lst), 2, rbind),
rbindlist(lapply(lst, data.frame)),
unnest(lapply(lst, data.frame))
)
And the results:
Unit: microseconds
expr min lq mean median uq max neval
do.call(rbind, lst) 43.290 47.9760 55.63858 52.8845 62.703 101.307 100
Reduce(rbind, lst) 542.236 570.7985 620.99652 585.3020 610.518 1871.272 100
apply(simplify2array(lst), 2, rbind) 311.061 345.2010 382.22978 368.6315 388.268 1563.782 100
rbindlist(lapply(lst, data.frame)) 11827.884 12472.3190 13092.57937 12823.0995 13595.841 15833.736 100
unnest(lapply(lst, data.frame)) 12371.905 12927.9765 13514.24261 13236.1360 14008.655 16121.143 100
Just out of curiosity, I have performed these benchmark tests for data.frame
inputs as well and there the picture is very different:
# packages
require(data.table)
require(tidyr)
require(microbenchmark)
# data
lst <- replicate(100, as.data.frame(matrix(rnorm(16), ncol = 4)), simplify=FALSE)
# benchmark test
microbenchmark(
do.call(rbind, lst),
Reduce(rbind, lst),
apply(simplify2array(lapply(lst, as.matrix)), 2, rbind),
rbindlist(lst),
unnest(lst)
)
with results:
Unit: microseconds
expr min lq mean median uq max neval
do.call(rbind, lst) 12406.716 12944.2660 13746.8552 13571.966 14564.056 16333.128 100
Reduce(rbind, lst) 36316.866 38450.7765 39894.9806 39299.610 40325.395 100949.158 100
apply(simplify2array(lapply(lst, as.matrix)), 2, rbind) 9577.717 9940.9930 10273.8674 10065.059 10291.996 12114.846 100
rbindlist(lst) 324.896 369.0770 397.7828 402.995 426.202 500.732 100
unnest(lst) 926.487 974.9095 1011.7322 1010.834 1033.596 1171.051 100