1

I have a list of vectors in R:

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

[[2]]
[1] 7 9 1 4

[[3]]
[1] 8 2 1

[[4]]
[1] 8 9 0 7

And I want to make a dataframe out of them. The problem is, I can't simply use unlist and then reorganize, because not all the vectors are the same length – I want NAs in my dataframe when that happens. The final result should look like this:

Col1  Col2  Col3  Col4
1     2     3     4
7     9     1     4
8     2     1     NA
8     9     0     7

Is there a way to do this?

japem
  • 1,037
  • 5
  • 16
  • 30
  • 1
    Possible duplicate of [Converting nested list (unequal length) to data frame](http://stackoverflow.com/questions/27153979/converting-nested-list-unequal-length-to-data-frame) – MLavoie Feb 10 '17 at 10:31
  • Possible duplicate of [R list of data frames to data frame](http://stackoverflow.com/questions/42141889/r-list-of-data-frames-to-data-frame) – Uwe Feb 10 '17 at 11:24

4 Answers4

4

Using purrr you can do the following:

require(purrr)
L <- list(1:4, c(7,9,1,4), c(8,2,1), c(8,9,0,7))
map_df(L, ~as.data.frame(t(.)))

Which gives you:

  V1 V2 V3 V4
1  1  2  3  4
2  7  9  1  4
3  8  2  1 NA
4  8  9  0  7

Base R approach:

clen <- vapply(L, length, integer(1))
mat <- matrix(NA, nrow = length(L), ncol = max(clen))
for(i in seq_along(L)){
  mat[i, seq(1, clen[i])] <- L[[i]]
}
as.data.frame(mat)
Rentrop
  • 20,979
  • 10
  • 72
  • 100
3

Try this in base R (where ls is your list object):

data.frame(t(sapply(ls, function(x) x[1:max(lengths(ls))])))

Which given your data will give you:

#  X1 X2 X3 X4
#1  1  2  3  4
#2  7  9  1  4
#3  8  2  1 NA
#4  8  9  0  7

In general, c(1:5)[1:7] will give you

#[1]  1  2  3  4  5 NA NA
989
  • 12,579
  • 5
  • 31
  • 53
2

cbind.ts will work on objects of different lengths. Using that we can get the following one line base solution:

as.data.frame(t(unname(do.call("cbind", lapply(L, ts)))))

giving:

  V1 V2 V3 V4
1  1  2  3  4
2  7  9  1  4
3  8  2  1 NA
4  8  9  0  7

This could alternately be expressed as a magrittr pipeline:

library(magrittr)

L %>% 
  lapply(ts) %>% 
  do.call(what = "cbind") %>% 
  t %>% 
  unname %>% 
  as.data.frame

Note: We used this as the input:

L <- list(1:4, c(7, 9, 1, 4), c(8, 2, 1), c(8, 9, 0, 7))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
1

We could use the stri_list2matrix from stringi and convert to mode from character to integer

library(stringi)
m1 <- stri_list2matrix(L, byrow=TRUE)
mode(m1) <- "integer"
m1
#      [,1] [,2] [,3] [,4]
#[1,]    1    2    3    4
#[2,]    7    9    1    4
#[3,]    8    2    1   NA
#[4,]    8    9    0    7

matrix can be converted to data.frame with as.data.frame so

as.data.frame(m1)

data

L <- list(1:4, c(7, 9, 1, 4), c(8, 2, 1), c(8, 9, 0, 7))
akrun
  • 874,273
  • 37
  • 540
  • 662