R-从宽格式到长格式使用组合

时间:2019-01-22 21:45:37

标签: 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      982
3  C  345  325     <NA>

我想创建一个data.frame,其中Var1Var2Var3ID中的元素组合在一起。

我正在寻找的结果应如下所示:

> 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的{​​{1}}。

原始数据包含数百万个ID。

2 个答案:

答案 0 :(得分:2)

我们可以使用tidyverse来获得一个相当优雅的解决方案。总体思路是,我们可以使用separate_rowsVar3扩展为行,我们只需要将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

答案 1 :(得分:1)

使用tidyversesplitstackshape,您可以执行以下操作:

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”。