[英]lapply with nested list
我有一個嵌套列表,我想在最深的嵌套級別上lapply
as.data.frame
,然后在rbindlist
(從data.table
)提供所有內容。 這是我的數據:
a <- list(date="2017-01-01",ret=1:5)
b <- list(date="2017-01-02",ret=7:9)
lvl3 <- list(a,b)
lvl2 <- list(lvl3,lvl3)
lvl1 <- list(lvl2,lvl2,lvl2)
如果我只有lvl3,我會將其轉換為data.frame
並對數據進行rbind
:
rbindlist(lapply(lvl3,as.data.frame))
date ret
1: 2017-01-01 1
2: 2017-01-01 2
3: 2017-01-01 3
4: 2017-01-01 4
5: 2017-01-01 5
6: 2017-01-02 7
7: 2017-01-02 8
8: 2017-01-02 9
我如何從lvl1和rbind
所有嵌套的data.frames
做到這data.frames
? 這不起作用:
rbindlist(lapply(lvl1,as.data.frame))
所需結果包含48行:
date ret
1: 2017-01-01 1
2: 2017-01-01 2
3: 2017-01-01 3
4: 2017-01-01 4
5: 2017-01-01 5
6: 2017-01-02 7
7: 2017-01-02 8
8: 2017-01-02 9
9: 2017-01-01 1
10: 2017-01-01 2
11: 2017-01-01 3
12: 2017-01-01 4
13: 2017-01-01 5
14: 2017-01-02 7
15: 2017-01-02 8
16: 2017-01-02 9
17: 2017-01-01 1
18: 2017-01-01 2
19: 2017-01-01 3
20: 2017-01-01 4
21: 2017-01-01 5
22: 2017-01-02 7
23: 2017-01-02 8
24: 2017-01-02 9
25: 2017-01-01 1
26: 2017-01-01 2
27: 2017-01-01 3
28: 2017-01-01 4
29: 2017-01-01 5
30: 2017-01-02 7
31: 2017-01-02 8
32: 2017-01-02 9
33: 2017-01-01 1
34: 2017-01-01 2
35: 2017-01-01 3
36: 2017-01-01 4
37: 2017-01-01 5
38: 2017-01-02 7
39: 2017-01-02 8
40: 2017-01-02 9
41: 2017-01-01 1
42: 2017-01-01 2
43: 2017-01-01 3
44: 2017-01-01 4
45: 2017-01-01 5
46: 2017-01-02 7
47: 2017-01-02 8
48: 2017-01-02 9
您可以構建自己的遞歸函數,àla
f <- function(l) {
data.table::rbindlist(lapply(l, function(x) {
if(all(sapply(x, is.atomic))) as.data.table(x) else f(x)
}))
}
f(lvl1)
這將返回48行和2列的普通data.table。
另請注意,這適用於lvl1
, lvl2
和lvl3
而無需修改。
在我看來,@ docendo的一般解決方案是最好的,但是如果你知道它只是嵌套的兩個深...
library(magrittr)
lvl1 %>%
unlist(recursive=FALSE) %>%
unlist(recursive=FALSE) %>%
lapply(as.data.table) %>%
rbindlist
來自@lmo,這是無管的模擬(不需要magrittr):
do.call(
rbind,
lapply(
unlist(unlist(lvl1, recursive=FALSE), recursive=FALSE),
as.data.frame
)
)
可能有更優雅的方法,但將data.table與嵌套的foreach循環結合起來:
library(foreach)
library(data.table)
a <- list(date="2017-01-01",ret=1:5)
b <- list(date="2017-01-02",ret=7:9)
lvl3 <- list(a,b)
lvl2 <- list(lvl3,lvl3)
lvl1 <- list(lvl2,lvl2,lvl2)
o.3 <- foreach(i=1:length(lvl1)) %do% {
o.2 <- foreach(j=1:length(lvl1[[i]])) %do% {
o.1 <- foreach(k=1:length(lvl1[[i]][[j]])) %do% {
as.data.table(lvl1[[i]][[j]][[k]])
}
rbindlist(o.1)
}
rbindlist(o.2)
}
dat.final <- rbindlist(o.3)
我會選擇邪惡的包裹purrr
。 尤其是:
library(purrr)
(rbindlist(lapply(simplify_all((rbindlist((lvl1 %>% at_depth(3,data.frame))))),rbindlist)))
date ret
1: 2017-01-01 1
2: 2017-01-01 2
3: 2017-01-01 3
4: 2017-01-01 4
5: 2017-01-01 5
-----
44: 2017-01-01 4
45: 2017-01-01 5
46: 2017-01-02 7
47: 2017-01-02 8
48: 2017-01-02 9
使用do.call
進行丑陋的嵌套lapply
調用可以解決這個問題:
do.call(rbind,do.call(rbind,lapply(lvl1,function(x) lapply(x,function(y) do.call(rbind,lapply(y, function(z) as.data.frame(z)))))))
輸出:
> do.call(rbind,do.call(rbind,lapply(lvl1,function(x) lapply(x,function(y) do.call(rbind,lapply(y, function(z) as.data.frame(z)))))))
date ret
1 2017-01-01 1
2 2017-01-01 2
3 2017-01-01 3
4 2017-01-01 4
5 2017-01-01 5
6 2017-01-02 7
7 2017-01-02 8
8 2017-01-02 9
9 2017-01-01 1
10 2017-01-01 2
11 2017-01-01 3
12 2017-01-01 4
13 2017-01-01 5
14 2017-01-02 7
15 2017-01-02 8
16 2017-01-02 9
17 2017-01-01 1
18 2017-01-01 2
19 2017-01-01 3
20 2017-01-01 4
21 2017-01-01 5
22 2017-01-02 7
23 2017-01-02 8
24 2017-01-02 9
25 2017-01-01 1
26 2017-01-01 2
27 2017-01-01 3
28 2017-01-01 4
29 2017-01-01 5
30 2017-01-02 7
31 2017-01-02 8
32 2017-01-02 9
33 2017-01-01 1
34 2017-01-01 2
35 2017-01-01 3
36 2017-01-01 4
37 2017-01-01 5
38 2017-01-02 7
39 2017-01-02 8
40 2017-01-02 9
41 2017-01-01 1
42 2017-01-01 2
43 2017-01-01 3
44 2017-01-01 4
45 2017-01-01 5
46 2017-01-02 7
47 2017-01-02 8
48 2017-01-02 9
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.