2

I am trying to convert a simple list of varying lengths into a data frame as shown below. I would like to populate the missing values with NaN. I tried using ldply, rbind, as.data.frame() but I failed to get it into the format I want. Please help.

x=c(1,2)
y=c(1,2,3)
z=c(1,2,3,4)
a=list(x,y,z)

a
[[1]]
[1] 1 2

[[2]]
[1] 1 2 3

[[3]]
[1] 1 2 3 4

Output should be:

x   y   z
1   1   1
2   2   2
NaN 3   3
NaN NaN 4
Abi K
  • 631
  • 2
  • 7
  • 13

2 Answers2

2

Using rbind.fill.matrix from "plyr" gets you very close to what you're looking for:

> library(plyr)
> t(rbind.fill.matrix(lapply(a, t)))
  [,1] [,2] [,3]
1    1    1    1
2    2    2    2
3   NA    3    3
4   NA   NA    4
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
  • Thanks @Ananda. Is there anyway I can retain column headers and also get **dataframe** as opposed to a matrix – Abi K Jul 30 '13 at 16:18
  • @oostopitre, sure. Make sure you're using a named `list`, then you can do `setNames(data.frame(t(rbind.fill.matrix(lapply(a, t)))), names(a))` – A5C1D2H2I1M1N2O1R2T1 Jul 30 '13 at 16:23
2

This is a lot of code, so not as clean as Ananda's solution, but it's all base R:

maxl <- max(sapply(a,length))
out <- do.call(cbind, lapply(a,function(x) x[1:maxl]))
# out <- matrix(unlist(lapply(a,function(x) x[1:maxl])), nrow=maxl) #another way
out <- as.data.frame(out)
#names(out) <- names(a)

Result:

> out
  V1 V2 V3
1  1  1  1
2  2  2  2
3 NA  3  3
4 NA NA  4

Note: names of the resulting df will depend on the names of your list (a), which doesn't currently have names.

Thomas
  • 43,637
  • 12
  • 109
  • 140