R-使用组合从宽格式到长格式
假设我有以下数据库R-使用组合从宽格式到长格式,r,dataframe,reshape,R,Dataframe,Reshape,假设我有以下数据库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
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>
请注意:
中的元素由竖条隔开Var3
|
不在ID==C
中,因为outcome
对于该Var3
是ID
NA
原始数据由数百万个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”。这似乎是一个重复:与@markus相结合,确实存在大量从宽到长的条目,以及如何拆分字符串。我想,这里棘手的部分是通过ID正确地堆叠Var1-Var3和Var2-Var3,并高效地完成这项工作;df%%>%filter(ID!=“C”)%%>%sep=“\\\\\””%%>%gather(key,Var2,-ID,-Var3)%%>%select(-key)%%>%arrange(ID)?@markus在发布刷新页面之前,我没有看到你给我写过类似的答案。如果你想发布你的,我会删除我的,因为我认为
separate_rows
是解决这个问题的更合理的函数,即使str_split
和unnest
有相同的结果。@Mako212别担心。编辑您的答案并包括单独的行
(如果您愿意)。
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