Pregunta

I have list where the elementnames are ID-tags and contains a vector with numeric values. These are of unequal(!) length.

I want to transform it to a data frame where I have the ID in one column and the numeric values in another column. E.g.:

$`1`  
[1] 1 2   
$`2`  
[1] 1 2 3 
$`3`  
[1] 1   

To:

ID   Obs  
1    1  
1    2
2    1
2    2
2    3
3    1
¿Fue útil?

Solución

Here is one way:

## your list
ll <- list("1" = 1:2, "2" = 1:3, "3" = 1:2)
## convert to data.frame
dl <- data.frame(ID = rep(names(ll), sapply(ll, length)),
                 Obs = unlist(ll))

This gives:

> dl
   ID Obs
11  1   1
12  1   2
21  2   1
22  2   2
23  2   3
31  3   1
32  3   2

The first line in the data.frame() call is just some code to repeat the names() of the list the required number of times. The second line just unlists the list converting it into a vector.

Otros consejos

Use reshape2 and melt which has a method melt.list

.list <- list(`1` = 1:2, `2` = 1:3, `3` = 1:2)
library(reshape2)
melt(.list)
##   value L1
## 1     1  1
## 2     2  1
## 3     1  2
## 4     2  2
## 5     3  2
## 6     1  3
## 7     2  3

A good and still missing alternative to the already posted solutions is the stack-function:

df <- stack(ll)[2:1]

which gives:

> df
  ind values
1   1      1
2   1      2
3   2      1
4   2      2
5   2      3
6   3      1
7   3      2

Using setNames as well, you can get the exact desired format:

df <- setNames(stack(ll)[2:1], c('ID','Obs'))

which gives:

> df
  ID Obs
1  1   1
2  1   2
3  2   1
4  2   2
5  2   3
6  3   1
7  3   2

Used data:

ll <- list("1" = 1:2, "2" = 1:3, "3" = 1:2)

A solution using base functions

List <- list('1'=c(1,2), '2'= c(1,2,3), '3'=1)
x <- unlist(List)  # as suggested by Gavin Simpson
data.frame(ID=substr(names(x),1,1), Obs=x)
   ID Obs
11  1   1
12  1   2
21  2   1
22  2   2
23  2   3
3   3   1

If you want the rownames to be 1,2,3,4,5,6 the try this (using setNames):

data.frame(ID=substr(names(x),1,1), Obs=setNames(x, NULL))
  ID Obs
1  1   1
2  1   2
3  2   1
4  2   2
5  2   3
6  3   1

This solution is valid only if all names have the same length, otherwise it'll fail, and it'd be better using Gavin's solution. See for example:

List2 <- list('week1'=c(1,2), 'week2'= c(1,2,3), 'week3'=1)
x <- unlist(List2)  
data.frame(ID=substr(names(x),1,nchar(names(x)[1])-1), Obs=setNames(x, NULL))

    ID   Obs
1 week1   1
2 week1   2
3 week2   1
4 week2   2
5 week2   3
6 week3   1
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top