複数の値をひとつのセルにまとめる(マルチアンサー形式).R

 蛇蝎のごとく嫌って分解し続けてきたマルチアンサーを、今度は作ってみよう。
 基本はlong→wideへの変換だが、wideにされてできた列をuniteして一つのカラムに納める。つまりseparate_rowsの逆変換だ。
 結論としては下のようになる。

>test
 COL1 CAT
1    A   a
2    B  b1
3    B  b2
4    C  c1
5    C  c2
6    C  c3

> test %>% group_by(COL1) %>%
   mutate(CATNO = row_number()) %>%
   pivot_wider(names_prefix = "CAT", names_from = CATNO, values_from = CAT) %>%
   unite(col = CAT, starts_with("CAT"), sep = "|", na.rm = T)
# A tibble: 3 x 2
# Groups:   COL1 [3]
 COL1  CAT     
 <chr> <chr>   
1 A     a       
2 B     b1|b2   
3 C     c1|c2|c3

 group_by(COL1) %>% mutate(CATNO = row_number())とすることで、CAT列の隣にCATNO列をしている。CATNO列は、COL1の値ごとで上から順に行番号を振ったものだ。
 CAT列の値をそのまま列名にするのではなく、CAT列の値をvalueとして扱いたかったというのが理由だ。もう少し丁寧に書くと下のようになる。当然、NAになる列が出てくるので、unite()の際にはna.rm=Tとしている。

> test %>% group_by(COL1) %>% mutate(CATNO = row_number()) 
# A tibble: 6 x 3
# Groups:   COL1 [3]
 COL1  CAT   CATNO
 <chr> <chr> <int>
1 A     a         1
2 B     b1        1
3 B     b2        2
4 C     c1        1
5 C     c2        2
6 C     c3        3
> test %>% group_by(COL1) %>% mutate(CATNO = row_number()) %>%
   pivot_wider(names_prefix = "CAT", names_from = CATNO, values_from = CAT) 
# A tibble: 3 x 4
# Groups:   COL1 [3]
 COL1  CAT1  CAT2  CAT3 
 <chr> <chr> <chr> <chr>
1 A     a     NA    NA   
2 B     b1    b2    NA   
3 C     c1    c2    c3

 最終的に得られた結果(test1)をseparate_rows()すれば元に戻る。

> test1 %>% separate_rows(CAT, sep = "\\|")
# A tibble: 6 x 2
# Groups:   COL1 [3]
 COL1  CAT  
 <chr> <chr>
1 A     a    
2 B     b1   
3 B     b2   
4 C     c1   
5 C     c2   
6 C     c3   

以上。

いいなと思ったら応援しよう!