lapply和嵌套列表

4

我有一个嵌套列表,我想在最深的嵌套级别上使用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.framerbind:
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开始,并将所有嵌套的data.frame使用rbind连接起来?以下方式不可行:

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

rbindlist(lapply(lvl1,as.data.table)) 是不是? - amonk
@agerom 这不起作用。 - Pierre Lapointe
是的,我明白了,您介意发布您希望获得的结果吗? - amonk
3
将所有嵌套的数据框绑定在一起,如果没有嵌套的数据框,则返回NULL。使用lvl1 %>% unlist(recursive=FALSE) %>% unlist(recursive=FALSE) %>% lapply(as.data.table) %>% rbindlist,(结合magrittr)可以解决问题。应该有一种能够实现此目的的rapply函数,但我无法让它正常工作。 - Frank
同样地,这也可以使用 dplyr 来实现:lapply(lvl1, function(y) lapply(y, function(x) lapply(x, data.frame) %>% rbindlist) %>% rbindlist) %>% rbindlist - amatsuo_net
5个回答

5
你可以自己构建递归函数,就像这样:
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列的数据表格。另外请注意,它可以在不进行修改的情况下适用于lvl1、lvl2和lvl3。

那么不允许使用列表列,是吗?例如,L = list(x = 1:2, vals = list(1:2, 3:4)) - Frank
1
不,这种情况不行。你可以修改代码以检查至少一个列表元素是否是原子的。 - talat

3
@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
  )
)

1
@lmo 谢谢,已添加。 - Frank

2
也许有更优雅的方法,但结合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)

1
我会选择 wicked 包中的 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

3
你的结果是8行还是48行? - Frank

1
一个丑陋的嵌套lapply调用和do.call可以解决问题: 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接