【问题标题】:R - from wide to long format using combinationsR - 使用组合从宽格式到长格式
【发布时间】:2019-01-22 21:45:37
【问题描述】:

假设我有以下数据库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,其中Var1Var2 通过IDVar3 中的元素组合。

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

> 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 中,因为对于 IDVar3NA

原始数据由数百万个 ID 组成。

【问题讨论】:

  • @markus 确实,有很多关于从宽到长移动以及如何拆分字符串的条目。我想这里的棘手部分是按 ID 正确堆叠 Var1-Var3 和 Var2-Var3,并有效地做到这一点。
  • library(tidyverse); df %&gt;% filter(ID != "C") %&gt;% separate_rows(Var3, sep = "\\|") %&gt;% gather(key, Var2, -ID, -Var3) %&gt;% select(-key) %&gt;% arrange(ID) 呢?
  • @markus 在发布刷新页面之前,我没有看到您写过类似的答案。如果你想发布你的,我会删除我的,因为我认为separate_rows 是解决这个问题的更合乎逻辑的函数,即使str_splitunnest 具有相同的结果。
  • @Mako212 别担心。编辑您的答案,如果您愿意,可以添加 separate_rows

标签: r dataframe reshape


【解决方案1】:

我们可以使用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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-07
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      相关资源
      最近更新 更多