There is a list like this, starting from 1.
[[7158]]
[1] 81 72
[[7159]]
[1] 81 69
[[7160]]
[1] 81 79
[[7161]]
[1] 81 84
This needs to be changed to a data frame where the first number in each element is aligned in one data frame column, and the second number in each element is placed in the second column of a data frame. So it should end up like this
> data.frame("col1" = c(81, 81, 81, 81), "col2" = c(72, 69, 79, 84))
  col1 col2
1   81   72
2   81   69
3   81   79
4   81   84
I tried doing do.call(rbind.data.frame, my_list) but it seems to place the numbers in a huge number of columns, not coerce it down to the two columns needed.  It would be pretty straight forward to do this with a loop but what is the R way to do it? Thanks.
Converting a List to Vector in R Language – unlist() Function. unlist() function in R Language is used to convert a list to vector. It simplifies to produce a vector by preserving all components.
Just set the names:
mylist <- list(c(81,72), c(81,63), c(81,79))
setNames(do.call(rbind.data.frame, mylist), c("col1", "col2"))
#  col1 col2
#1   81   72
#2   81   63
#3   81   79
In contrast to some of the other solutions, this would also work for mixed data types:
mylist <- list(list("a", 72), list("b", 63), list("c", 79))
res <- setNames(do.call(rbind.data.frame, mylist), c("col1", "col2"))
str(res)
#'data.frame':  3 obs. of  2 variables:
# $ col1: Factor w/ 3 levels "a","b","c": 1 2 3
# $ col2: num  72 63 79
                        You can try any of the following:
do.call(rbind, my_list)
t(simplify2array(my_list))
library(stringi)
stri_list2matrix(my_list, byrow = TRUE)
All of the above would produce a two column matrix with the data that you describe, so you can then use as.data.frame to get a data.frame.
Timings for the above alternatives and @Roland's suggestion can be found at this Gist. To summarize, the "stringi" approach would be the fastest of the options presented so far. If I'm not mistaken, rbindlist in "data.table" should also support converting list of vectors--but I have not tested with the development version on GitHub to verify, so I haven't included that option here.
You can try with
Reduce( rbind, lapply(t1, t) )
                        Another idea:
mylist = list(c(81, 72), c(81, 69), c(81, 79), c(81, 84))
f4 = function(x) 
{
    tlist = lapply(seq_along(x[[1]]), 
                   function(i) unlist(lapply(x, "[[", i)))
    structure(tlist, class = "data.frame", 
              row.names = .set_row_names(as.integer(length(tlist[[1]]))), 
              names = paste("col", seq_along(tlist), sep = ""))
}
f4(mylist)
#  col1 col2
#1   81   72
#2   81   69
#3   81   79
#4   81   84
And a benchmark with the other options:
library(stringi)              
f1 = function(x)
  setNames(as.data.frame(type.convert(stri_list2matrix(x, byrow = TRUE))), 
           paste("col", seq_along(x[[1]]), sep = ""))
f2 = function(x)
  setNames(do.call(rbind.data.frame, x), 
           paste("col", seq_along(x[[1]]), sep = ""))
f3 = function(x)
  setNames(as.data.frame(Reduce(rbind, lapply(x, t))), 
           paste("col", seq_along(x[[1]]), sep = "")) 
myls = replicate(1e3, sample(1e2), simplify = F)
identical(f1(myls), f2(myls))
#[1] TRUE
identical(f1(myls), f3(myls))
#[1] TRUE
identical(f1(myls), f4(myls))
#[1] TRUE
microbenchmark::microbenchmark(f1(myls), f2(myls), f3(myls), f4(myls), times = 10)
#Unit: milliseconds
#     expr       min        lq    median        uq       max neval
# f1(myls)  57.66834  58.46979  59.39131  61.43861 102.27333    10
# f2(myls) 393.81459 404.29019 418.03128 422.87740 494.79857    10
# f3(myls) 288.39078 299.51680 305.21727 314.75482 374.48683    10
# f4(myls)  52.54991  53.26575  55.34472  59.25559  75.19658    10
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With