将给定列表转换为数据帧

时间:2012-01-10 07:40:59

标签: r

我有以下列表:

$id1
$id1[[1]]
         A              B               
        "A"            "B"                
$id1[[2]]
         A             B 
        "A"           "A1" 
$id2
$id2[[1]]
         A              B               
        "A2"           "B2" 

以R-pastable形式:

dat = structure(list(SampleTable = structure(list(id2 = list(structure(c("90", "7"), .Names = c("T", "G")), structure(c("90", "8"), .Names = c("T", "G"))), id1 = structure(c("1", "1"), .Names = c("T", "G"))), .Names = c("id2", "id1"))), .Names = "SampleTable") 

我希望将此给定列表转换为以下数据帧:

id1   A    B
id1   A    A1 
id2   A2   B2 

3 个答案:

答案 0 :(得分:5)

您的数据结构(显然是未命名的1行data.frames列表的命名列表)有点复杂:最简单的可能是使用循环来构建data.frame。

可以直接使用do.calllapplyrbind来完成,但即使您熟悉这些功能,它也不是非常易读。

# Sample data 
d <- list(
  id1 = list(
    data.frame( x=1, y=1 ),
    data.frame( x=2, y=2 )
  ),
  id2 = list(
    data.frame( x=3, y=3 ),
    data.frame( x=4, y=4 )
  ),
  id3 = list(
    data.frame( x=5, y=5 ),
    data.frame( x=6, y=6 )
  )
)

# Convert
d <- data.frame(
  id=rep(names(d), unlist(lapply(d,length))),
  do.call( rbind, lapply(d, function(u) do.call(rbind, u)) )
)

其他解决方案,使用循环,如果你有一个参差不齐的数据结构,包含矢量(而不是data.frames),如评论中所述。

d <- structure(list(SampleTable = structure(list(id2 = list(structure(c("90", "7"), .Names = c("T", "G")), structure(c("90", "8"), .Names = c("T", "G"))), id1 = structure(c("1", "1"), .Names = c("T", "G"))), .Names = c("id2", "id1"))), .Names = "SampleTable") 
result <- list()
for(i in seq_along(d$SampleTable)) {
  id <- names(d$SampleTable)[i]
  block <- d$SampleTable[[i]]
  if(is.atomic(block)) {
    block <- list(block)
  }
  for(row in block) {
    result <- c(result, list(data.frame(id, as.data.frame(t(row)))))
  }    
}
result <- do.call(rbind, result)

答案 1 :(得分:1)

请注意!我无法融化并投射这种粗糙的数据(我尝试了一个多小时......)我将在这里留下这个答案,以表明对于这种操作,也可以使用重塑的pacakge。

使用vincent的示例数据,您可以使用reshape包中的melt和cast:

library(reshape)
res = cast(melt(d))[-1]
names(res) = c("id","x","y")
res
   id x y
1 id1 1 1
2 id2 3 3
3 id3 5 5
4 id1 2 2
5 id2 4 4
6 id3 6 6

结果data.frame中的顺序不一样,但结果是相同的。代码有点短。我使用[-1]删除melt也返回的第一列。此附加变量是列表列表中各个data.frames的列索引。看看melt(d)的结果,希望能让它更清晰。

答案 2 :(得分:0)

这让你有点麻烦。 dat对象上方有一个额外的“图层”,因此使用dat[[1]]更容易:

dfrm <- data.frame(dat[[1]], stringsAsFactors=FALSE)
names(dfrm) <- sub("\\..+$", "", names(dfrm))

> dfrm
  id2 id2 id1
T  90  90   1
G   7   8   1
> t(dfrm)
    T    G  
id2 "90" "7"
id2 "90" "8"
id1 "1"  "1"