Reputation: 4061
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
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
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