I have the following list of lists:
list_1 <- list(a = 2, b = 3)
list_2 <- list(a=c(5,6), b= c(2,3))
list_3 <- list(a=c(10,5,8,1), b=c(9,6,2,9))
list_4 <- list(a=c(2,5,58), b=c(69,6,23))
mylist <- list(list_1, list_2, list_3, list_4)
names(mylist)<- c("list_1", "list_2", "list_3", "list_4")
Now what I want is to extract all the a and b values from the lists and save them either as a data.frame with the corresponding list names as a ID column like:
[ID] [a] [b]
[1] list_1 2 3
[2] list_2 5 2
[3] list_2 6 3
[4] list_3 10 9
[5] list_3 5 6
[6] list_3 8 2
[7] list_3 1 9
[8] list_4 2 69
[9] list_4 5 6
[10] list_4 58 23
or as variables, such that a
contains all a values, b
contains all b values, and ID
contains the corresponding list IDs:
[a]
2 5 6 10 5 8 1 2 5 58
[b]
3 2 3 9 6 2 9 69 6 23
[ID]
"list_1" "list_2" "list_2" "list_3" "list_3" "list_3" "list_3" "list_4" "list_4" "list_4"
I tried the second approach with a for loop but couldn't mange to archive the desired result. But even if I could manage that I don't know how I would solve the ID thing. It would be great if the solution could be a general one, because I have many such lists of different lengths.
In base R, you could loop through the names of mylist
, for each name generating a data frame with that name as the ID
variable and all variables from the relevant element of mylist
. Then you could combine all the generated data frames together with do.call
and rbind
:
do.call(rbind, lapply(names(mylist), function(x) data.frame(c(ID=x, mylist[[x]]))))
# ID a b
# 1 list_1 2 3
# 2 list_2 5 2
# 3 list_2 6 3
# 4 list_3 10 9
# 5 list_3 5 6
# 6 list_3 8 2
# 7 list_3 1 9
# 8 list_4 2 69
# 9 list_4 5 6
# 10 list_4 58 23
I would just rbind
the lists and add the row names as ID
. This way you don't need to worry about the column names at all. Or you can just leave the row.names
as the ID
and just settle with do.call(rbind.data.frame, mylist)
res <- do.call(rbind.data.frame, mylist)
res$ID <- sub("\\..*", "", row.names(res))
row.names(res) <- NULL
res
# a b ID
# 1 2 3 list_1
# 2 5 2 list_2
# 3 6 3 list_2
# 4 10 9 list_3
# 5 5 6 list_3
# 6 8 2 list_3
# 7 1 9 list_3
# 8 2 69 list_4
# 9 5 6 list_4
# 10 58 23 list_4
Alternately you could also do
res <- do.call(rbind.data.frame, mylist)
as.list(cbind(res, ID = row.names(res)))
# $a
# [1] 2 5 6 10 5 8 1 2 5 58
#
# $b
# [1] 3 2 3 9 6 2 9 69 6 23
#
# $ID
# [1] list_1 list_2.2 list_2.3 list_3.4 list_3.5 list_3.6 list_3.7 list_4.8 list_4.9 list_4.10
# Levels: list_1 list_2.2 list_2.3 list_3.4 list_3.5 list_3.6 list_3.7 list_4.10 list_4.8 list_4.9
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