How to convert a list of lists to a dataframe - non-identical lists

r

Solution

Any function using `data.frame(.)` on each element of the list before binding would be terribly inefficient (not to mention unnecessary). Here's another way using `data.table`'s `rbindlist` (from v1.9.3) which you can get here.

require(data.table) ## 1.9.3
rbindlist(lisnotOK, fill=TRUE)
#     a b     c    d
# 1:  1 2    hi   NA
# 2: NA 2 hello nope

It works on list-of-lists (as in this question), data.frames and data.tables.

If not this, then I'd go with Ananda's `list2mat` function (if your types are all identical).

Benchmarks on Ananda's `L2` data:

fun1 <- function(inList) ldply(inList, as.data.frame)
fun2 <- function(inList) list2mat(inList)
fun3 <- function(inList) rbindlist(inList, fill=TRUE)
fun4 <- function(inList) rbind_all(lapply(inList, as.data.frame))

microbenchmark(fun1(L2), fun2(L2), fun3(L2), fun4(L2), times = 10)
# Unit: milliseconds
#      expr         min          lq      median          uq         max neval
#  fun1(L2) 1927.857847 2161.432665 2221.999940 2276.241366 2366.649614    10
#  fun2(L2)   12.039652   12.167613   12.361629   12.483751   16.040885    10
#  fun3(L2)    1.225929    1.374395    1.473621    1.510876    1.858597    10
#  fun4(L2) 1435.153576 1457.053482 1492.334965 1548.547706 1630.443430    10

Note: I've used `as.data.frame(.)` instead of `data.frame(.)` (former is slightly faster).

Problem

I have a list where each element is a named list, but the elements are not the same everywhere. I have read solutions on how to convert lists of lists to dataframes here and here, but none of this works when the lists are not identical. Example - note I have mixed types as well, it is fine if the solution coerces everything to character. ``` lisnotOK <- list(list(a=1, b=2, c="hi"), list(b=2, c="hello", d="nope")) ``` The result should simply have NA where a column cannot be filled by a list, just like `rbind.fill` from plyr, or `rbind_all` from dplyr. Example ``` lisOK <- list(list(a=1, b=2, c="hi"), list(a=3, b=5, c="bye")) # One of many solutions do.call(rbind.data.frame, lisOK) # gives a b c 2 1 2 hi 21 3 5 bye ``` Any solution that uses `rbind`, or tries to make `lisnotOK` into a matrix will fail, whereas any examples in the posts linked above don't work, even when I try to use `rbind_all` or `rbind.fill`. One solution is an ugly for loop where each successive list is changed to a dataframe, and uses `rbind_all` to bind to a dataframe. Does anyone know an efficient solution?

Original source

Related problems