繁体   English   中英

R 用匹配改变多列

[英]R Mutating multiple columns with matching

我正在处理一个适合我的研究的大型数据集。 假设我有 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,对应于“hours1”中的 3,它位于“A”列下。 ID 3 在“group1”中有 B,对应于“hours1”中的 5,位于“B”列下。 在“组 2”中,ID 4 具有 C,对应于在“C”列下找到的 hours2 中的 5。

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

一种方法是将一列中的所有“小时”列和另一列中的“组”列组合在一起。 这可以使用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())

另一种使用dplyr方法可以将 group 和 hours 变量分开来计算所需的变量,然后与原始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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM