jmb
jmb

Reputation: 665

R: Converting nested list to dataframe and get names of list levels als factors

I have a nested list:

list1 <- list("A"=c(1,1,1), "B"=c(2,2,2), "C"=c(3,3,3))
list2 <- list("F1" = list1, "F2" = list1)

and I would like to get the last level of the list (containing the vector) as a dataframe and I would like to get the levels of the list as factors:

  Level1 Level2 V1 V2 V3
1     F1      A  1  1  1
2     F1      B  2  2  2
3     F1      C  3  3  3
4     F2      A  1  1  1
5     F2      B  2  2  2
6     F2      C  3  3  3

The first part is nicely given by:

data.frame(matrix(unlist(list2), ncol=3, byrow=T))

However, I did not find a nice way to also get the list-level-names as factors in the same dataframe. Any ideas? :)

Edit: The procedure should work up to p dimensions.

Upvotes: 5

Views: 3387

Answers (3)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193527

melt from "reshape2" has a method for lists. Perhaps it can be used in this case. Something like this:

library(reshape2)
dcast(cbind(
  coln = sequence(rapply(list2, length)), 
  melt(list2)), L1 + L2 ~ coln, 
  value.var = "value")
#   L1 L2 1 2 3
# 1 F1  A 1 1 1
# 2 F1  B 2 2 2
# 3 F1  C 3 3 3
# 4 F2  A 1 1 1
# 5 F2  B 2 2 2
# 6 F2  C 3 3 3

Upvotes: 6

Roland Seubert
Roland Seubert

Reputation: 335

With your own solution providing the values in columns X1, X2 and X3 already, you can do the following to get the first two columns Level1 and Level2 from the names of your two lists:

level1 <- as.factor(rep(names(list2), each = length(list1)))
level2 <- as.factor(rep(names(list1), times = length(list2)))
data.frame(Level1 = level1, Level2 = level2, matrix(unlist(list2), ncol=3, byrow=T))

which will result in this:

  Level1 Level2 X1 X2 X3
1     F1      A  1  1  1
2     F1      B  2  2  2
3     F1      C  3  3  3
4     F2      A  1  1  1
5     F2      B  2  2  2
6     F2      C  3  3  3

Upvotes: 2

agstudy
agstudy

Reputation: 121568

You can unlist just one level , than convert rownames to columns, and join the all in a single data.frame:

xx <- do.call(rbind,unlist(list2,recursive = FALSE))
cbind.data.frame(do.call(rbind,strsplit(rownames(xx),'.',fixed=TRUE))
                ,xx)

      1 2 1 2 3
F1.A F1 A 1 1 1
F1.B F1 B 2 2 2
F1.C F1 C 3 3 3
F2.A F2 A 1 1 1
F2.B F2 B 2 2 2
F2.C F2 C 3 3 3

Upvotes: 2

Related Questions