将列表列表转换为R中的数据帧

时间:2015-08-28 03:13:52

标签: r data.table

我正在使用R中的嵌套列表,并且遇到了rbindlist的问题。我的列表看起来像这样

L <- list(list(list(c(0,0)),list(c(0,0)),list(c(33,37))), list(list(c(0,0)),list(c(0,0)),list(c(29,33))))

导致:

[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[1] 0 0


[[1]][[2]]
[[1]][[2]][[1]]
[1] 0 0


[[1]][[3]]
[[1]][[3]][[1]]
[1] 33 37



[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[1] 0 0


[[2]][[2]]
[[2]][[2]][[1]]
[1] 0 0


[[2]][[3]]
[[2]][[3]][[1]]
[1] 29 33

我要做的是将每个子列表折叠成一个看起来像这样的数据框(这个结果是我想从上面的第一组列表中得到的结果):

config alpha start end
1        1     0    0
1        2     0    0
1        3     33   37
2        1     0    0
2        2     0    0
2        3     29   33

但是某些列表相对于子列表中的其他列表具有不同的数量的子列表。例如,像这样的列表(中间有2个子列表而不是3个1子列表子列表)。

L <- list(list(c(0,0)), list(c(1,4),c(5,9)), list(c(0,0)) )
[[1]]
[[1]][[1]]
[1] 0 0


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

[[2]][[2]]
[1] 5 9


[[3]]
[[3]][[1]]
[1] 0 0

当我尝试使用rbindlist时出现此错误:

> rbindlist(lapply(master_init, as.list))
Error in rbindlist(lapply(master_init, as.list)) : 
  Column 2 of item 50 is length 2, inconsistent with first column of that item which is length 1. rbind/rbindlist doesn't recycle as it already expects each item to be a uniform list, data.frame or data.table

我知道错误意味着什么但不知道如何解决它。想法?

2 个答案:

答案 0 :(得分:1)

我们可以通过melt/dcast执行此操作。我们设置list元素的名称,melt以将list转换为data.frame。我们创建了一个序列列('ind'),在将'data.frame'转换为'data.table'之后,按L列分组,即L1,L2,L3。然后,我们使用dcast的devel版本中的data.table从'long'重新变为'wide'。

library(reshape2)
library(data.table)#v1.9.5+
d1 <- melt(setNames(L, seq_along(L)))
setDT(d1)[, ind:= c('start', 'end')[1:.N], .(L1, L2, L3)]
res <- setnames(dcast(d1, L1+L2~ind, value.var='value'), 
               1:2, c('config', 'alpha'))
res[,c(1:2, 4:3), with=FALSE]
#   config alpha start end
#1:      1     1     0   0
#2:      1     2     0   0
#3:      1     3    33  37
#4:      2     1     0   0
#5:      2     2     0   0
#6:      2     3    29  33

对于第二个list('L1'),我们执行相同的过程。我们可以像上一种情况一样更改列名。

d2 <- melt(setNames(L1, seq_along(L1)))
setDT(d2)[, ind:= 1:.N, .(L1, L2)]
dcast(d2, L1+L2~ind, value.var='value')

答案 1 :(得分:1)

虽然这不是一个完整的答案,但它可能会让你开始走上正确的道路。

L1 <- list(list(list(c(0,0)),list(c(0,0)),list(c(33,37))), list(list(c(0,0)),list(c(0,0)),list(c(29,33))))
L2 <- list(list(c(0,0)), list(c(1,4),c(5,9)), list(c(0,0)))

as.data.frame(matrix(unlist(L1), ncol = 2, byrow = TRUE))

  V1 V2
1  0  0
2  0  0
3 33 37
4  0  0
5  0  0
6 29 33

as.data.frame(matrix(unlist(L2), ncol = 2, byrow = TRUE))
  V1 V2
1  0  0
2  1  4
3  5  9
4  0  0