使用 dplyr 传播和加入不等大小列表的列表
Spread and join list of lists of unequal sizes with dplyr
我有兴趣做一个相当复杂的连接,但我一直找不到答案。这是一个示例数据集:
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" 的函数重复。
我在收集、团结和传播方面取得了一些进步。但是我觉得效率很低,把bind_rows的列表,然后散开,再组合回列表。也许我在这里错了?
我的真实数据是一个大列表(115 个元素)。当我 bind_rows 我的列表时,我最终得到 233561 个观察结果。所以我有很多 id,node_age 一直到 115,这就是我瞄准列表结构的原因。
提前致谢。
我们可以绑定行,然后 split
通过 'id' 和 dcast
到 'wide' 格式
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
中的列,请将 'key' 创建为 factor
列,并按该顺序指定 levels
以更改 order
在 spread
dat_list %>%
bind_rows %>%
split(.$id) %>%
map(~ .x %>%
gather(key, val, Number:node_age) %>%
group_by(key) %>%
mutate(rn = row_number()) %>%
ungroup %>%
arrange(rn) %>%
unite(keyage, key, age) %>%
mutate(keyage = factor(keyage, levels = unique(keyage))) %>%
select(-rn) %>%
spread(keyage, val))
#$T1
# A tibble: 3 x 8
# id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#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
# A tibble: 3 x 8
# id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 T2 1.2 1 0 1 1 1 2
#2 T2 2.3 NA NA 2 0 2 1
#3 T2 3.4 NA NA NA NA 3 0
我有兴趣做一个相当复杂的连接,但我一直找不到答案。这是一个示例数据集:
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" 的函数重复。
我在收集、团结和传播方面取得了一些进步。但是我觉得效率很低,把bind_rows的列表,然后散开,再组合回列表。也许我在这里错了?
我的真实数据是一个大列表(115 个元素)。当我 bind_rows 我的列表时,我最终得到 233561 个观察结果。所以我有很多 id,node_age 一直到 115,这就是我瞄准列表结构的原因。
提前致谢。
我们可以绑定行,然后 split
通过 'id' 和 dcast
到 'wide' 格式
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
中的列,请将 'key' 创建为 factor
列,并按该顺序指定 levels
以更改 order
在 spread
dat_list %>%
bind_rows %>%
split(.$id) %>%
map(~ .x %>%
gather(key, val, Number:node_age) %>%
group_by(key) %>%
mutate(rn = row_number()) %>%
ungroup %>%
arrange(rn) %>%
unite(keyage, key, age) %>%
mutate(keyage = factor(keyage, levels = unique(keyage))) %>%
select(-rn) %>%
spread(keyage, val))
#$T1
# A tibble: 3 x 8
# id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#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
# A tibble: 3 x 8
# id Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 T2 1.2 1 0 1 1 1 2
#2 T2 2.3 NA NA 2 0 2 1
#3 T2 3.4 NA NA NA NA 3 0