llaffin
llaffin

Reputation: 4061

Nested list: Ordering it into a dataframe

I have a list of nested lists. Each nested list is of different lengths. Each value in the lists has a name assigned to it. I would like to make a data frame from the lists, but order the lists so that each value is in the correct column in a data frame.

It's hard to explain in English, I hope this example code will explain:

list <- list(1,1:2,1:3)
names(list[[1]]) <- "a"
names(list[[2]]) <- c("c", "a")
names(list[[3]]) <- c("a","c","b")

table <- matrix(NA, nrow = 3, ncol = 3)
colnames(table) <- c("a","b","c")  

> list
[[1]]
a 
1 

[[2]]
c a 
1 2 

[[3]]
a c b 
1 2 3 

> table
      a  b  c
[1,] NA NA NA
[2,] NA NA NA
[3,] NA NA NA  

I want to order the lists into the table like so:

>table
          a  b  c
list[[1]] 1 NA NA
list[[2]] 2 NA  1
list[[3]] 1  3  2

so that the name of the value in the list matches the name of the column in the table, and list[[1]] goes to row 1, list[[2]] goes to row 2, etc.

Any help would be appreciated.

(Additional Info:

My actual dataset has tens of thousands of nested lists, the longest list has length 26.

Im Running 32-bit R 3.2.4 on Windows 10)

Upvotes: 3

Views: 175

Answers (2)

rawr
rawr

Reputation: 20811

You could turn them into data frames and use data.table::rbindlist which will work on lists of lists

edit 2 -- using the gtools::smartbind on the rapply works for a more complicated nested list of list:

list <- list(1,1:2,1:3)
names(list[[1]]) <- "a"
names(list[[2]]) <- c("c", "a")
names(list[[3]]) <- c("a","c","b")

list <- c(list(list, list(list)), list)

l <- rapply(list, function(x) data.frame(as.list(x)), how = 'list')
do.call(gtools::smartbind, l)

#   a  c  b
# 1 1  1  3
# 2 1  1  3
# 3 1 NA NA
# 4 2  1 NA
# 5 1  2  3

edit 1 -- this version might be more efficient

list <- list(1,1:2,1:3)
names(list[[1]]) <- "a"
names(list[[2]]) <- c("c", "a")
names(list[[3]]) <- c("a","c","b")

library('data.table')
list <- rapply(list, function(x) setDT(as.list(x)), how = 'list')

# [[1]]
#    a
# 1: 1
# 
# [[2]]
#    c a
# 1: 1 2
# 
# [[3]]
#    a c b
# 1: 1 2 3

rbindlist(list, fill = TRUE)[, c('a','b','c'), with = FALSE]

#    a  b  c
# 1: 1 NA NA
# 2: 2 NA  1
# 3: 1  3  2

original

list <- list(1,1:2,1:3)
names(list[[1]]) <- "a"
names(list[[2]]) <- c("c", "a")
names(list[[3]]) <- c("a","c","b")

list <- rapply(list, function(x) data.frame(as.list(x)), how = 'list')

# [[1]]
#   a
# 1 1
# 
# [[2]]
#   c a
# 1 1 2
# 
# [[3]]
#   a c b
# 1 1 2 3

data.frame(data.table::rbindlist(list, fill = TRUE))[, c('a','b','c')]

#   a  b  c
# 1 1 NA NA
# 2 2 NA  1
# 3 1  3  2

Upvotes: 2

mtoto
mtoto

Reputation: 24198

We can try smartbind() from gtools package in combination with do.call().

library('gtools')
do.call("smartbind", list)
#  a  c  b
#1 1 NA NA
#2 2  1 NA
#3 1  2  3

Upvotes: 5

Related Questions