R convert list with multiple string lengths to data frame

Viewed 51

I have a list:

l1<-list(A=1:10, B=100:120, C=300:310, D=400:430)

How do I convert it to dataframe with 2 columns:

    C1 C2 
R1  1  A 
R2  2  A 
...
R10 10 A
R11  100  B
R12  101  B
....
R73  429  D
R73  430  D 

I tried:

df1 <- data.frame(matrix(unlist(l1), nrow=length(l1), byrow=T))

But I'm getting an error because the vectors in my list have multiple lengths. Also my actual list consist of Dates and not just integers.

3 Answers

Just use stack:

stack(l1)

> head(stack(l1))
  values ind
1      1   A
2      2   A
3      3   A
4      4   A
5      5   A
6      6   A
> tail(stack(l1))
   values ind
68    425   D
69    426   D
70    427   D
71    428   D
72    429   D
73    430   D

Update

stack won't work with dates. If you have actual date objects, you can do:

data.frame(ind = rep(names(l1), lengths(l1)), 
           val = as.Date(unlist(l1), origin = "1970-01-01"))

or

data.frame(ind = rep(names(l1), lengths(l1)), val = do.call(c, l1))

Sample data:

l1<-list(A=Sys.Date()+(1:10), 
         B=Sys.Date()+(100:120), 
         C=Sys.Date()+(300:310), 
         D=Sys.Date()+(400:430))

Here's one method: Similar to #Duck answer using Map and do.call

tmp <- Map(data.frame,N = l1,L = names(l1))
out <- do.call(rbind,tmp)
rownames(out) <- NULL

> tail(out)
     N L
68 425 D
69 426 D
70 427 D
71 428 D
72 429 D
73 430 D

Maybe a long solution, but using mapply() and do.call() you can reach the expected result. First, you can extract the names of the list as well as the number of elements. Then, using mapply() you can create a list for the first column in your desired result. After that you combine mapply(), do.call(), rbind() and cbind() to end up with df. Here the code:

#Code
#names
v1 <- names(l1)
#length
v2 <- unlist(lapply(l1, length))
#Create values
l2 <- mapply(function(x,y) rep(x,y),v1,v2)
#Bind
df <- as.data.frame(do.call(rbind,mapply(cbind,l2,l1)))
df$V2 <- as.numeric(df$V2)

Output (some rows):

head(df,15)
   V1 V2
1   A  1
2   A 24
3   A 25
4   A 37
5   A 69
6   A 70
7   A 71
8   A 72
9   A 73
10  A  2
11  B  3
12  B  4
13  B  5
14  B  6
15  B  7
Related