複数の値をひとつのセルにまとめる(マルチアンサー形式).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
以上。