[英]Converting a list of list of data.frames to a single data.frame in R
我有一個data.frames
list
list
(見下面的L
)。
我想知道是否可以將L
轉換為我所需的輸出,如下所示 ,這是一個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)))
期望的輸出( data.frame
):
d SD id
1 3 1
2 4 1
2 1 2
3 2 2
7 6 2
8 7 2
5 3 3
6 4 3
8 1 3
9 2 3
4 6 3
5 7 3
我們可以嘗試對L
每個列表進行rbinding並添加一個新列,該列表示列表編號,最后使用do.call
和rbind
將整個列表放入一個數據幀中。
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
的bind_rows
和purrr::map
可能會稍微短bind_rows
,但是這purrr::map
id
變量作為列表的名稱( A
, B
, C
)而不是序列,這不應該很難改變。
library(dplyr)
bind_rows(purrr::map(L, bind_rows), .id = "id") %>%
mutate(id = match(id, unique(id)))
我們可以在base R
使用lapply/Map
。 我們可以使用lapply
循環遍歷list
, rbind
嵌套list
元素,然后使用Map
創建一個新列並對外部list
元素進行rbind
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
根據注釋,如果我們需要從內部list
的names
添加另一列
out1 <- do.call(rbind, Map(cbind, lapply(L, function(dat)
do.call(rbind, Map(cbind, dat, es.type = names(dat)))), id = seq_along(L)))
row.names(out1) <- NULL
out1
# d SD es.type id
#1 1 3 Short 1
#2 2 4 Short 1
#3 2 1 Short 2
#4 3 2 Short 2
#5 7 6 Long1 2
#6 8 7 Long1 2
#7 5 3 Short 3
#8 6 4 Short 3
#9 8 1 Long1 3
#10 9 2 Long1 3
#11 4 6 Long2 3
#12 5 7 Long2 3
如果有..\\\\d+
並想要刪除
out1 <- do.call(rbind, Map(cbind, lapply(L, function(dat)
do.call(rbind, Map(cbind, dat,
es.type = sub("\\.*\\d+$", "", names(dat))))), id = seq_along(L)))
row.names(out1) <- NULL
out1
# d SD es.type id
#1 1 3 Short 1
#2 2 4 Short 1
#3 2 1 Short 2
#4 3 2 Short 2
#5 7 6 Long 2
#6 8 7 Long 2
#7 5 3 Short 3
#8 6 4 Short 3
#9 8 1 Long 3
#10 9 2 Long 3
#11 4 6 Long 3
#12 5 7 Long 3
這是使用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
注意:這里我使用了基本R的transform
,可以用dplyr的mutate
代替
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
和Long2
必須成為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
可以從解析行名稱中檢索id
和es.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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.