Andre_k
Andre_k

Reputation: 1728

Transpose list rows into a dataframe

Suppose this is my list structure

lst=list(structure(c("level1", "level2", "level4", "level5","18", "abc", "pqr", "lmn"),
         .Dim = c(4L, 2L)), 
     structure(c("level1", "level2", "level3", "level5", "level6", "20", "xyz", "hive", "foo", "bar"), 
        .Dim = c(5L, 2L)),
     structure(c("level1", "level3", "level4", "level5","level6", "22", "dark", "yellow","foobar", "blue"), 
        .Dim = c(5L, 2L)),
     structure(c("level1", "level2", "level3", "level5","level6","level7","24", "dvd", "dxs","glass", "while","though"), 
     .Dim = c(6L, 2L))
     )

Expecting O/P something like this

     level1 level2  level3  level4  level5  level6  level7
1)     18       abc     NA      pqr     lmn     NA      NA
2)     20       xyz     hive    NA      foo     bar     NA
3)     22       NA      dark    yellow  foobar  blue    NA
4)     24       dvd     dxs     NA      glass   while   though  

The first column from all list should be transposed and accordingly, corresponding data should get looked up to their rows.

Trying to do transpose of all rows to column itself giving error

 unique(t(list_temp[[c(1,2)]][,1]))
ERROR:Error in list_temp[[c(1, 2)]][, 1] : incorrect number of dimensions

Also tried with

apply(list_temp,1,function(x){list_temp[[x]][,1]})

But gave me

Error in apply(list_temp, 1, function(x) { : 
  dim(X) must have a positive length

Any suggestion on how should it be done.

Thanks.

Upvotes: 3

Views: 2051

Answers (2)

Jaap
Jaap

Reputation: 83215

Two approaches:

1) using the -package

With:

library(data.table)
dcast(rbindlist(lapply(lst, as.data.table), idcol = 'id'),
      id ~ V1, value.var = 'V2')[, id := NULL][]

you get:

   level1 level2 level3 level4 level5 level6 level7
1:     18    abc     NA    pqr    lmn     NA     NA
2:     20    xyz   hive     NA    foo    bar     NA
3:     22     NA   dark yellow foobar   blue     NA
4:     24    dvd    dxs     NA  glass  while though

2) using base R

With:

reshape(transform(do.call(rbind.data.frame, lst),
                  r = rep(seq_along(lst), lengths(lst)/2)),
        idvar = 'r', timevar = 'V1', direction = 'wide')[,-1]

you get:

   V2.level1 V2.level2 V2.level4 V2.level5 V2.level3 V2.level6 V2.level7
1         18       abc       pqr       lmn      <NA>      <NA>      <NA>
5         20       xyz      <NA>       foo      hive       bar      <NA>
10        22      <NA>    yellow    foobar      dark      blue      <NA>
15        24       dvd      <NA>     glass       dxs     while    though

Upvotes: 5

Sotos
Sotos

Reputation: 51582

Here is another idea using Reduce to merge the data frames, then transpose and do some cleaning, i.e.

m1 <- t(Reduce(function(...) merge(..., by = 'V1', all = TRUE), lapply(lst, as.data.frame)))
colnames(m1) <- m1[1,]
row.names(m1) <- NULL
final_d <- as.data.frame(m1[-1,], stringsAsFactors = FALSE)

which gives,

   level1 level2 level4 level5 level3 level6 level7
1     18    abc    pqr    lmn   <NA>   <NA>   <NA>
2     20    xyz   <NA>    foo   hive    bar   <NA>
3     22   <NA> yellow foobar   dark   blue   <NA>
4     24    dvd   <NA>  glass    dxs  while though

Upvotes: 2

Related Questions