将混合长度命名列表转换为data.frame

Jef*_*len 17 r dataframe

我有以下格式的列表:

[[1]]
[[1]]$a
[1] 1

[[1]]$b
[1] 3

[[1]]$c
[1] 5

[[2]]       
[[2]]$c
[1] 2

[[2]]$a
[1] 3
Run Code Online (Sandbox Code Playgroud)

存在可能的"键"的预定义列表(a,b并且c,在这种情况下),并且列表中的每个元素("行")将具有为这些键中的一个或多个定义的值.我正在寻找一种从上面的列表结构到一个data.frame的快速方法,在这种情况下,它将如下所示:

  a  b c
1 1  3 5
2 3 NA 2
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激!


附录

我正在处理一个最多有50,000行和3-6列的表,其中指定了大多数值.我将从JSON中获取表格并尝试快速将其转换为data.frame结构.

以下是一些代码,用于创建我将使用的比例的样本列表:

ids <- c("a", "b", "c")
createList <- function(approxSize=100){     
    set.seed(1234)

    fifth <- round(approxSize/5)

    list <- list()
    list[1:(fifth*5)] <- rep(
        list(list(a=1, b=2, c=3), 
                 list(a=3, b=4, c=5),
                 list(a=7, c=9),
                 list(c=6, a=8, b=3),
                 list(b=6)), 
        fifth)

    list
}
Run Code Online (Sandbox Code Playgroud)

只需创建一个包含approxSize50,000的列表即可在此大小的列表上测试性能.

flo*_*del 9

这是一个简短的答案,我怀疑它会非常快.

> library(plyr)
> rbind.fill(lapply(x, as.data.frame))
  a  b c
 1 1  3 5
 2 3 NA 2
Run Code Online (Sandbox Code Playgroud)

  • 是啊.调用`as.data.frame` 50k次的部分在我的机器上需要27秒,然后`rbind.fill()`在传递50k data.frames时完全窒息.这对于小问题非常简洁,但看起来并不像它可以很好地扩展. (2认同)

Jos*_*ien 9

这是我最初的想法.它不会加速你的方法,但它确实大大简化了代码:

# makeDF <- function(List, Names) {
#     m <- t(sapply(List, function(X) unlist(X)[Names], 
#     as.data.frame(m)
# }    

## vapply() is a bit faster than sapply()
makeDF <- function(List, Names) {
    m <- t(vapply(List, 
                  FUN = function(X) unlist(X)[Names], 
                  FUN.VALUE = numeric(length(Names))))
    as.data.frame(m)
}

## Test timing with a 50k-item list
ll <- createList(50000)
nms <- c("a", "b", "c")

system.time(makeDF(ll, nms))
# user  system elapsed 
# 0.47    0.00    0.47 
Run Code Online (Sandbox Code Playgroud)

  • 你可以通过手动将列表转换成数据框而不用复制来削减另外约30%:`class(m)< - "data.frame"; attr(m,"row.names")< - c(NA_integer_,-length(m [[1]]))` (2认同)