【发布时间】:2012-09-20 07:24:23
【问题描述】:
我有一个列表,其中元素名称是 ID 标签,并且包含一个带有数值的向量。它们的长度不等(!)。
我想将其转换为一个数据框,其中一列中有 ID,另一列中有数值。例如:
$`1`
[1] 1 2
$`2`
[1] 1 2 3
$`3`
[1] 1
收件人:
ID Obs
1 1
1 2
2 1
2 2
2 3
3 1
【问题讨论】:
我有一个列表,其中元素名称是 ID 标签,并且包含一个带有数值的向量。它们的长度不等(!)。
我想将其转换为一个数据框,其中一列中有 ID,另一列中有数值。例如:
$`1`
[1] 1 2
$`2`
[1] 1 2 3
$`3`
[1] 1
收件人:
ID Obs
1 1
1 2
2 1
2 2
2 3
3 1
【问题讨论】:
这是一种方法:
## 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))
这给出了:
> dl
ID Obs
11 1 1
12 1 2
21 2 1
22 2 2
23 2 3
31 3 1
32 3 2
data.frame() 调用中的第一行只是将列表中的names() 重复所需次数的一些代码。第二行只是取消列出将其转换为向量的列表。
【讨论】:
使用reshape2 和melt,它们有一个方法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
【讨论】:
stack-function 是已经发布的解决方案的一个很好但仍然缺少的替代方案:
df <- stack(ll)[2:1]
给出:
> df ind values 1 1 1 2 1 2 3 2 1 4 2 2 5 2 3 6 3 1 7 3 2
同样使用setNames,您可以获得所需的确切格式:
df <- setNames(stack(ll)[2:1], c('ID','Obs'))
给出:
> df ID Obs 1 1 1 2 1 2 3 2 1 4 2 2 5 2 3 6 3 1 7 3 2
使用过的数据:
ll <- list("1" = 1:2, "2" = 1:3, "3" = 1:2)
【讨论】:
使用基函数的解决方案
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
如果您希望 rownames 为 1,2,3,4,5,6,请尝试以下操作(使用 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
此解决方案仅在所有名称的长度相同时才有效,否则会失败,最好使用 Gavin 的解决方案。例如:
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
【讨论】:
x <- unlist(List),不是吗?