使用dplyr传播和合并大小不等的列表

时间:2018-11-06 19:01:14

标签: r join dplyr spread

我有兴趣进行相当复杂的联接,但找不到答案。这是一个示例数据集:

dat2 <- data.frame(age = c(2,2), id = c("T1", "T2"), Height = c(1.1,1.2), Number = c(1,1), node_age = c(0, 0))
dat3 <- data.frame(age = c(3,3,3,3), id = c("T1", "T1", "T2", "T2"), Height = c(1.1,2.2, 1.2, 2.3), Number = c(1,2,1,2), node_age = c(1,0,1,0))
dat4 <- data.frame(age = c(4,4,4,4,4,4), id = c("T1", "T1", "T1", "T2", "T2", "T2"), Height = c(1.1,2.2,3.3,1.2, 2.3,3.4 ), Number = c(1,2,3,1,2,3), node_age = c(2,1,0,2,1,0))
dat_list <- list(dat2, dat3, dat4)

我想使用此列表并将所有内容结合在一起,以便结果看起来像这样:

$`T1`
  id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
1 T1    1.1        1          0        1          1        1          2
2 T1    2.2       NA         NA        2          0        2          1
3 T1    3.3       NA         NA       NA         NA        3          0

$T2
  id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
4 T2    1.2        1          0        1          1        1          2
5 T2    2.3       NA         NA        2          0        2          1
6 T2    3.4       NA         NA       NA         NA        3          0

其中的输出是按id列出的列表,并且将“ Number”和“ node_age”作为“ age”的功能重复。

我在聚集,团结和传播方面取得了一些进展。但是我觉得将list的bind_rows然后传播,然后再组合回列表效率不高。也许我在这里错了?

我的真实数据是一个很大的列表(115个元素)。当我列表的bind_rows时,我得到233561个观察结果。所以我有很多id,而node_age直到115,这就是为什么我要使用列表结构的原因。

谢谢。

1 个答案:

答案 0 :(得分:1)

我们可以将行绑定,然后将split的'id'和dcast绑定为'宽'格式

library(tidyverse)
library(data.table)
dat_list %>%
   bind_rows %>% 
   split(.$id) %>% 
   map(~  dcast(as.data.table(.x), id + Height ~ age, 
              value.var = c( 'Number', 'node_age')))
#$T1
#   id Height Number_2 Number_3 Number_4 node_age_2 node_age_3 node_age_4
#1: T1    1.1        1        1        1          0          1          2
#2: T1    2.2       NA        2        2         NA          0          1
#3: T1    3.3       NA       NA        3         NA         NA          0

#$T2
#   id Height Number_2 Number_3 Number_4 node_age_2 node_age_3 node_age_4
#1: T2    1.2        1        1        1          0          1          2
#2: T2    2.3       NA        2        2         NA          0          1
#3: T2    3.4       NA       NA        3         NA         NA          0

或者我们使用gather/spread代替dcast

dat_list %>% 
   bind_rows %>%
   split(.$id) %>%
   map(~ .x  %>% 
            gather(key, val, Number:node_age) %>%
            unite(keyage, key, age) %>%
            spread(keyage, val))
#$T1
#  id Height node_age_2 node_age_3 node_age_4 Number_2 Number_3 Number_4
#1 T1    1.1          0          1          2        1        1        1
#2 T1    2.2         NA          0          1       NA        2        2
#3 T1    3.3         NA         NA          0       NA       NA        3

#$T2
#  id Height node_age_2 node_age_3 node_age_4 Number_2 Number_3 Number_4
#1 T2    1.2          0          1          2        1        1        1
#2 T2    2.3         NA          0          1       NA        2        2
#3 T2    3.4         NA         NA          0       NA       NA        3

如果我们需要特定order中的列,请以指定的factor来创建'key'作为levels列,以更改{ {1}}

order