在R中将data.frame列表的列表转换为单个data.frame

时间:2019-08-12 01:46:49

标签: r list function dataframe lapply

我有一个{{1}的一个list中的一个list(请参阅下面的data.frames)。

我想知道是否有可能将L转换为下面显示的所需输出

L

所需的输出(a data.frame

L <- list(A = list(Short = data.frame(d = 1:2, SD = 3:4)), 
          B = list(Short = data.frame(d = 2:3, SD = 1:2), Long1 = data.frame(d = 7:8, SD = 6:7)),
          C = list(Short = data.frame(d = 5:6, SD = 3:4), Long1 = data.frame(d = 8:9, SD = 1:2), 
               Long2 = data.frame(d = 4:5, SD = 6:7)))

4 个答案:

答案 0 :(得分:3)

我们可以尝试重新绑定L中的每个列表,并添加一个新列来表示列表编号,最后使用do.callrbind将整个列表放入一个数据帧。

output <- do.call(rbind, lapply(seq_along(L), function(x) 
                          transform(do.call(rbind, L[[x]]), id = x)))
rownames(output) <- NULL

output
#   d SD id
#1  1  3  1
#2  2  4  1
#3  2  1  2
#4  3  2  2
#5  7  6  2
#6  8  7  2
#7  5  3  3
#8  6  4  3
#9  8  1  3
#10 9  2  3
#11 4  6  3
#12 5  7  3

dplyr的{​​{1}}与bind_rows一起使用可能会更短一些,但这会给变量purrr::map作为列表的名称(id,{ {1}},A),而不是应该不难更改的顺序。

B

答案 1 :(得分:1)

我们可以在Date()中使用let data = request.body let tiemStamp = new Timestamp(data.time._seconds,data.time._nanoseconds) 。我们可以遍历lapply/Mapbase Rlist嵌套的lapply元素,然后用外部的rbindlist创建新列Map个元素

rbind

根据注释,如果我们需要从内部list的{​​{1}}中添加另一列

out <- do.call(rbind, Map(cbind, lapply(L, function(x) 
              do.call(rbind, x)), id = seq_along(L)))
row.names(out) <- NULL
out
#   d SD id
#1  1  3  1
#2  2  4  1
#3  2  1  2
#4  3  2  2
#5  7  6  2
#6  8  7  2
#7  5  3  3
#8  6  4  3
#9  8  1  3
#10 9  2  3
#11 4  6  3
#12 5  7  3

如果有names并想要删除

list

答案 2 :(得分:0)

这是使用purrr的flatten_dfr的另一种可能的方法:

library(purrr)

transform(flatten_dfr(L), id = rep(seq_along(L), times = map(L, ~sum(lengths(.x)))))
#>    d SD id
#> 1  1  3  1
#> 2  2  4  1
#> 3  2  1  2
#> 4  3  2  2
#> 5  7  6  2
#> 6  8  7  2
#> 7  5  3  3
#> 8  6  4  3
#> 9  8  1  3
#> 10 9  2  3
#> 11 4  6  3
#> 12 5  7  3

NB:在这里,我使用了基数R的transform,可以将其替换为dplyr的mutate

答案 3 :(得分:0)

rbindlist()是一项便捷功能,可以从多个列表中创建一个data.table。对于此嵌套列表,必须递归应用两次。

此外,它具有idcol参数,该参数在结果中创建一列,显示这些行来自哪个列表项。

library(data.table)
rbindlist(lapply(L, rbindlist, idcol = "es.type"), idcol = "id")
    id es.type d SD
 1:  A   Short 1  3
 2:  A   Short 2  4
 3:  B   Short 2  1
 4:  B   Short 3  2
 5:  B   Long1 7  6
 6:  B   Long1 8  7
 7:  C   Short 5  3
 8:  C   Short 6  4
 9:  C   Long1 8  1
10:  C   Long1 9  2
11:  C   Long2 4  6
12:  C   Long2 5  7

现在,OP已请求id为数字和Long1 and Long2 must become Long。这可以通过对结果列进行后续操作来实现:

rbindlist(lapply(L, rbindlist, idcol = "es.type"), idcol = "id")[
  , id := rleid(id)][
    , es.type := sub("\\d+$", "", es.type)][]
    id es.type d SD
 1:  1   Short 1  3
 2:  1   Short 2  4
 3:  2   Short 2  1
 4:  2   Short 3  2
 5:  2    Long 7  6
 6:  2    Long 8  7
 7:  3   Short 5  3
 8:  3   Short 6  4
 9:  3    Long 8  1
10:  3    Long 9  2
11:  3    Long 4  6
12:  3    Long 5  7

在基数R中,我们可以通过

do.call("rbind", lapply(L, do.call, what = "rbind"))

返回

          d SD
A.Short.1 1  3
A.Short.2 2  4
B.Short.1 2  1
B.Short.2 3  2
B.Long1.1 7  6
B.Long1.2 8  7
C.Short.1 5  3
C.Short.2 6  4
C.Long1.1 8  1
C.Long1.2 9  2
C.Long2.1 4  6
C.Long2.2 5  7
可以通过解析行名来检索

ides.type,例如,

DF <- do.call("rbind", lapply(L, do.call, what = "rbind"))
id <- stringr::str_extract(row.names(DF), "^[^.]*")
# create sequence number (that's what data.table::rleid() does)
DF$id <- c(1L, cumsum(head(id, -1L) != tail(id, -1L)) + 1L)
DF$es.type <- stringr::str_extract(row.names(DF), "(?<=\\.)[^.0-9]*")
row.names(DF) <- NULL
DF
   d SD id es.type
1  1  3  1   Short
2  2  4  1   Short
3  2  1  2   Short
4  3  2  2   Short
5  7  6  2    Long
6  8  7  2    Long
7  5  3  3   Short
8  6  4  3   Short
9  8  1  3    Long
10 9  2  3    Long
11 4  6  3    Long
12 5  7  3    Long