R - 使用组合从宽格式到长格式
R - from wide to long format using combinations
假设我有以下数据库 df
.
df <- data.frame(ID= c("A", "B", "C"),
Var1 = c(234, 12, 345),
Var2 = c(4, 555, 325),
Var3 = c("45|221|2", "982", NA))
> df
ID Var1 Var2 Var3
1 A 234 4 45|221|2
2 B 12 555 982
3 C 345 325 <NA>
我想创建一个 data.frame,其中 Var1
和 Var2
通过 ID
与 Var3
中的元素组合。
我正在寻找的结果应该如下所示:
> outcome
ID VarA VarB
1 A 234 45
2 A 234 221
3 A 234 2
4 A 4 45
5 A 4 221
6 A 4 2
7 B 12 982
8 B 555 982
注意:
Var3
中的元素用竖线分隔|
ID == C
不在 outcome
中,因为 Var3
是 NA
ID
.
原始数据由数百万个ID组成。
我们可以使用 tidyverse
来获得一个相当优雅的解决方案。一般的想法是我们可以使用 separate_rows
将 Var3
扩展成行,我们只需要将 Var1/Var2
变成合适的长格式,这样我们就不会不必要地重复值。
library(tidyverse)
library(stringr)
df %>% gather(variable, value, -ID, -Var3) %>% # pull Var1 and Var2 into
# a single pair of key/value columns
separate_rows(Var3, sep = "\|") %>% # split Var3 into rows for each value
drop_na(Var3) %>% # drop the NA rows
select(ID, VarA = value, VarB = Var3, -variable) %>%
arrange(ID)
ID VarA VarB
1 A 234 45
2 A 234 221
3 A 234 2
4 A 4 45
5 A 4 221
6 A 4 2
7 B 12 982
8 B 555 982
使用 tidyverse
和 splitstackshape
你可以:
df %>%
filter(!is.na(Var3)) %>%
select(-Var3) %>%
gather(var, VarA, -ID) %>%
select(-var) %>%
full_join(df %>%
filter(!is.na(Var3)) %>%
cSplit("Var3", sep = "|") %>%
select(-Var1, -Var2) %>%
gather(var, VarB, -ID, na.rm = TRUE) %>%
select(-var), by = c("ID" = "ID")) %>%
arrange(ID, VarA, VarB)
ID VarA VarB
1 A 4 2
2 A 4 45
3 A 4 221
4 A 234 2
5 A 234 45
6 A 234 221
7 B 12 982
8 B 555 982
首先,它过滤掉 "Var3" 上有 NA 的行。其次,它将数据从宽格式转换为长格式,没有变量 "Var3"。最后,它执行与 df 的完全连接,其中过滤掉 "Var3" 上带有 NA 的行,并根据“|”拆分 "Var3"然后转换为宽格式到长格式,没有 "Var1" 和 "Var2".
假设我有以下数据库 df
.
df <- data.frame(ID= c("A", "B", "C"),
Var1 = c(234, 12, 345),
Var2 = c(4, 555, 325),
Var3 = c("45|221|2", "982", NA))
> df
ID Var1 Var2 Var3
1 A 234 4 45|221|2
2 B 12 555 982
3 C 345 325 <NA>
我想创建一个 data.frame,其中 Var1
和 Var2
通过 ID
与 Var3
中的元素组合。
我正在寻找的结果应该如下所示:
> outcome
ID VarA VarB
1 A 234 45
2 A 234 221
3 A 234 2
4 A 4 45
5 A 4 221
6 A 4 2
7 B 12 982
8 B 555 982
注意:
Var3
中的元素用竖线分隔|
ID == C
不在outcome
中,因为Var3
是NA
ID
.
原始数据由数百万个ID组成。
我们可以使用 tidyverse
来获得一个相当优雅的解决方案。一般的想法是我们可以使用 separate_rows
将 Var3
扩展成行,我们只需要将 Var1/Var2
变成合适的长格式,这样我们就不会不必要地重复值。
library(tidyverse)
library(stringr)
df %>% gather(variable, value, -ID, -Var3) %>% # pull Var1 and Var2 into
# a single pair of key/value columns
separate_rows(Var3, sep = "\|") %>% # split Var3 into rows for each value
drop_na(Var3) %>% # drop the NA rows
select(ID, VarA = value, VarB = Var3, -variable) %>%
arrange(ID)
ID VarA VarB
1 A 234 45
2 A 234 221
3 A 234 2
4 A 4 45
5 A 4 221
6 A 4 2
7 B 12 982
8 B 555 982
使用 tidyverse
和 splitstackshape
你可以:
df %>%
filter(!is.na(Var3)) %>%
select(-Var3) %>%
gather(var, VarA, -ID) %>%
select(-var) %>%
full_join(df %>%
filter(!is.na(Var3)) %>%
cSplit("Var3", sep = "|") %>%
select(-Var1, -Var2) %>%
gather(var, VarB, -ID, na.rm = TRUE) %>%
select(-var), by = c("ID" = "ID")) %>%
arrange(ID, VarA, VarB)
ID VarA VarB
1 A 4 2
2 A 4 45
3 A 4 221
4 A 234 2
5 A 234 45
6 A 234 221
7 B 12 982
8 B 555 982
首先,它过滤掉 "Var3" 上有 NA 的行。其次,它将数据从宽格式转换为长格式,没有变量 "Var3"。最后,它执行与 df 的完全连接,其中过滤掉 "Var3" 上带有 NA 的行,并根据“|”拆分 "Var3"然后转换为宽格式到长格式,没有 "Var1" 和 "Var2".