R tidyverse:转置但保持一列完整

R tidyverse: transposing but keeping one column intact

我知道有很多 post 关于这个话题。但是,我选择制作一个新的 post 因为

  1. 许多解决方案都在 reshape2 中,但我试图尽量减少此项目中使用的包的数量。所以我强烈希望 tidyverse 解决方案
  2. 我缺乏理解和适当改变其他 post 解决方案的能力。

感谢您的理解。

假设我有一个数据集:

test.dat <- tibble(pair = rep(c("1 v 2","1 v 3", "1 v 4" ,"2 v 3", "2 v 4", "3 v 4"),2),
                   name = c(rep("Louis",6),rep("Paul",6)),
                   Case1 = rpois(12,5),
                   Case2 = rpois(12,6),
                   Case3 = rpois(12,2),
                   Case4 = rpois(12,1)
> head(test.dat,2)
# A tibble: 2 x 6
  pair  name  Case1 Case2 Case3 Case4
  <chr> <chr> <int> <int> <int> <int>
1 1 v 2 Louis    11     7     0     0
2 1 v 3 Louis     3     9     3     1

我的目标是在保持 name 列不变的情况下进行转置。

test.want <- tibble(Case= rep(c("Case1","Case2","Case3","Case4"),2),
                    name = c(rep("Louis",4),rep("Paul",4)),
                    `1 v 2` = NA,
                    `1 v 3` = NA,
                    `1 v 4` = NA,
                    `2 v 3` = NA,
                    `2 v 4` = NA,
                    `3 v 4` = NA)
> head(test.want,2)
# A tibble: 2 x 8
  Case  name  `1 v 2` `1 v 3` `1 v 4` `2 v 3` `2 v 4` `3 v 4`
  <chr> <chr> <lgl>   <lgl>   <lgl>   <lgl>   <lgl>   <lgl>  
1 Case1 Louis NA      NA      NA      NA      NA      NA     
2 Case2 Louis NA      NA      NA      NA      NA      NA   

从关于使用 tidyverse 的其他 post 来看,解决方案似乎是先使用 pivot_longer(),然后再使用 pivot_wider。但是,我不能超出这个部分。

test <- test.dat %>% 
  pivot_longer(cols=starts_with("Case"))   #add names_repair argument?

Error: Failed to create output due to bad names.
* Choose another strategy with `names_repair`

问题在于 name 列与使用 pivot_longer 创建的默认列之间存在冲突,这会导致“名称”列重复。将 pivot_longer 中的 names_to 指定为 "Case" 以避免重复

library(dplyr)
library(tidyr)
test.dat %>%
  pivot_longer(cols = starts_with("Case"), names_to = "Case") %>% 
  pivot_wider(names_from = pair, values_from = value)

-输出

# A tibble: 8 x 8
#  name  Case  `1 v 2` `1 v 3` `1 v 4` `2 v 3` `2 v 4` `3 v 4`
#  <chr> <chr>   <int>   <int>   <int>   <int>   <int>   <int>
#1 Louis Case1       3       3      11       4       8       2
#2 Louis Case2       5       7       4       6       4       5
#3 Louis Case3       3       1       0       2       4       2
#4 Louis Case4       1       0       0       2       1       1
#5 Paul  Case1       5       2       5       4       5       3
#6 Paul  Case2       6       6       2       1       9       4
#7 Paul  Case3       0       3       2       2       2       2
#8 Paul  Case4       0       0       1       1       0       0