【问题标题】:R Mutating multiple columns with matchingR通过匹配改变多列
【发布时间】:2020-12-25 10:26:24
【问题描述】:

我正在处理一个适合我的研究的大型数据集。假设我有 4 个观察值(记录)和 5 列如下:

x <- data.frame("ID" = c(1, 2, 3, 4),
                "group1" = c("A", NA, "B", NA), 
                "group2" = c("B", "A", NA, "C"),
                "hours1" = c(3, NA, 5, NA),
                "hours2" = c(1, 2, NA, 5))

> x
ID group1 group2 hours1 hours2
 1      A      B      3      1
 2   <NA>      A     NA      2
 3      B   <NA>      5     NA
 4   <NA>      C     NA      5

“group1”和“group2”是参考列,包含A、B和C的字符值,最后两列“hours1”和“hours2”显然是数字表示小时。

“group1”列对应“hours1”列;同样,“group2”对应“hours 2”。

我想根据与“hours1”和“hours2”的值匹配的参考列的值A、B和C创建多个列,如下所示:

ID group1 group2 hours1 hours2  A  B  C
 1      A      B      3      1  3  1 NA
 2   <NA>      A     NA      2  2 NA NA
 3      B   <NA>      5     NA NA  5 NA
 4   <NA>      C     NA      5 NA NA  5

例如,ID 1 在“group1”中有 A,对应于在“A”列下的“hours1”中的 3。 ID 3 在“group1”中有 B,对应于在“B”列下的“hours1”中的 5。在“组 2”中,ID 4 有 C,对应于“C”列下的 hours2 中的 5。

有没有办法使用 R 来做到这一点?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    一种方法是将所有“小时”列合并到一个列中,将“组”列合并到另一列中。这可以使用pivot_longer 来完成。之后我们可以得到宽格式的数据,并与原始数据连接。

    library(dplyr)
    library(tidyr)
    
    x %>%
      pivot_longer(cols = -ID, 
                   names_to = c('.value'), 
                   names_pattern = '(.*?)\\d+', 
                   values_drop_na = TRUE) %>%
      pivot_wider(names_from = group, values_from = hours) %>%
      left_join(x, by = 'ID') %>%
      select(ID, starts_with('group'), starts_with('hour'), everything())
    
    # A tibble: 4 x 8
    #     ID group1 group2 hours1 hours2     A     B     C
    #  <dbl> <chr>  <chr>   <dbl>  <dbl> <dbl> <dbl> <dbl>
    #1     1 A      B           3      1     3     1    NA
    #2     2 NA     A          NA      2     2    NA    NA
    #3     3 B      NA          5     NA    NA     5    NA
    #4     4 NA     C          NA      5    NA    NA     5
    

    对于 OP 的数据集,我们可以稍微修改代码以达到预期的效果。

    zz %>%
      pivot_longer(cols = -id, 
                   names_to = c('.value'), 
                   names_pattern = '(.*)_', 
                   values_drop_na = TRUE) %>%
      arrange(fu2a) %>%
      pivot_wider(names_from = fu2a, values_from = fu2b) %>%
      left_join(zz, by = 'id') %>%
      select(id, starts_with('fu2a'), starts_with('fu2b'), everything())
    

    【讨论】:

    • 它适用于示例,因此我将此脚本应用于我的数据并稍作修改(即 ID --> id; 转换为 data.frame),但随后出现错误消息:“错误:无法组合 fu2a_1 和 fu2b_1 。”如果您不介意,我将使用 dput(df[1:7, 1:7]) 更新帖子。
    • @toumai 将pivot_longer 中的names_pattern 部分更改为names_pattern = '(.*)_' 并保持其他所有内容相同。
    • 有效!太感谢了!!!我还有一个问题。新列可以按顺序排列吗?
    • 他们现在在 [PERP 01]` [PERP 03] NA [PERP 05] [PERP 02]... 但想成为 [PERP 01]` [PERP 02] [PERP 03] ...
    • 是的,我们可以在使用pivot_wider之前arrange他们。检查答案中的更新。
    【解决方案2】:

    使用dplyr 的另一种方法可以分离组和小时变量以计算所需变量,然后与原始x 合并:

    library(tidyverse)
    #Data
    x <- data.frame("ID" = c(1, 2, 3, 4),
                    "group1" = c("A", NA, "B", NA), 
                    "group2" = c("B", "A", NA, "C"),
                    "hours1" = c(3, NA, 5, NA),
                    "hours2" = c(1, 2, NA, 5),stringsAsFactors = F)
    #Reshape
    x %>% 
      left_join(x %>% select(1:3) %>%
                  pivot_longer(cols = -ID) %>% 
                  group_by(ID) %>% mutate(id=1:n()) %>%
                  left_join(x %>% select(c(1,4:5)) %>%
                              pivot_longer(cols = -ID) %>%
                              rename(name2=name,value2=value) %>%
                              group_by(ID) %>% mutate(id=1:n())) %>%
                  filter(!is.na(value)) %>% select(ID,value,value2) %>%
                  pivot_wider(names_from = value,values_from=value2))
     
    

    输出:

      ID group1 group2 hours1 hours2  A  B  C
    1  1      A      B      3      1  3  1 NA
    2  2   <NA>      A     NA      2  2 NA NA
    3  3      B   <NA>      5     NA NA  5 NA
    4  4   <NA>      C     NA      5 NA NA  5
    

    【讨论】:

      猜你喜欢
      • 2015-05-12
      • 2022-01-18
      • 2022-01-15
      • 2019-01-17
      • 2021-11-27
      • 2021-05-14
      • 1970-01-01
      • 2018-03-31
      • 2021-02-20
      相关资源
      最近更新 更多