5

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.

A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
jmb
  • 625
  • 7
  • 11
  • `t(rbind.data.frame(list2))` gets you close - you only need to create variables from the rownames – user20650 Oct 04 '14 at 13:00
  • Thanks! The problem is that the list names vary (they are values of parameters in a simulation) so I can't just use substr to cut out the factors. – jmb Oct 04 '14 at 13:05

3 Answers3

6

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
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
2

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
agstudy
  • 119,832
  • 17
  • 199
  • 261
  • Thank you! This is a nice solution, however I was looking for a procedure that works for p dimensions (Sorry for not being specific about that in the first place) – jmb Oct 04 '14 at 13:48
2

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
Roland Seubert
  • 315
  • 3
  • 9
  • Thanks! It works very well, however, I was hoping for a procedure that works up to p dimensions (Sorry for not being specific about that in the first place) – jmb Oct 04 '14 at 14:28