マルチアンサーの分割のその先.R

要約

・分割したら元のデータに連結したい → tidyr::separate()
・ただし分割数が未定や多すぎる場合には注意が必要

str_sprit()では力不足かもしれない

 おそらく、何かしらの繰り返し処理や、局所的な結果を得たい場合にはstringr::str_split()がベターな解になるのだろうけれど、データ全体を変換するのには多分向いていないというか、もっと適した関数があるはずだ。
 何しろ、分離したらたいていは元のテーブルにくっつけるか置換したくなるものだし、そんなことを思いついていない人間が過去にいないはずはない。

tidyr::separate()

tidyr::separate(data, col, into, sep = "区切り文字",
remove = TRUE, convert = FALSE, extra = "warn", fill = "warn", ...)

引数
 col :対象列
 into :分離後の値を放り込む列名(ベクタ)
 sep :区切り文字; 整数で与えると正なら左から、負なら右からn文字で分割

オプション
 remove :元の値がある列(=col列)を削除
 convert :データ型を変換する; デフォルトFalseのままだと全部Factor?Charactor?
 extra : 分割後の要素数が用意した列数(into)より多いときに
      "warn" 警告が出るだけ
      "drop" 収まり切らなかったものは捨てる
      "merge" 残ったものはまとめて最後列
 #あと省略

 tidyr::は、パッケージ群であるtidyverse::にstringr::やdplyr::とともに含まれているデータ変形用の関数群だ。やっとたどり着いた…。

 オプションや挙動については上記のリンクが詳しいので割愛。
 分割したら、先頭から順に各列に放り込まれる。
 マルチアンサーとしてまとめられた中の値の数が予想できる場合には、予めその分の列を確保しておく。そうでない場合や、手なりで作られたデータを相手にする場合には、extra = warnにしておいたほうがフールプルーフになる。
 またこのとき、remove = Tであれば、intoで指定した列に分離後の値が格納される(直感的に正しい方の動作)。
 一方、規定値のremove = Fだと、残ったcol列も使って格納することになる。つまり、"intoの列数+1列(col)"に格納するのでintoの列が1つ余るし、intoで系統的な名前を確保しておいたのに使われないということが発生する。

 というのはあるにしろ、分離して、各列に1つずつ分けて放り込むということができそうだ。
 ただし、上記リンクにあるような、tidyな(整然とした)データには、これだけではまだ遠い。

tidyr::separate()の次にするべき処理は何か

name x_n5
smp1 1|2|3|2|3
smp2 4|3|1|1|2

 以前の記事で使ったマルチアンサーなデータの例だ。
 便宜上、5連ガチャ引いた結果がデータになっていて、Rarity(レアリティ)のC, R, SR, SSR, URがそれぞれ1~5に割り付けられていると思ってくれて構わない。
 じゃあなんでそう書かないのか?そりゃ以前の記事からコピ……便宜上である。10連3セットとか作るのめんどいじゃん。

 で、これをseparate()すると、次のようになる。特定の状態と紐づいたインデックスであって、実際には文字列だと思ってほしい。

separate(df, col=x_n5, sep="\\|", into = paste0("x", 1:5), remove = T)
name x1 x2 x3 x4 x5
smp1 1 2 3 2 3
smp2 4 3 1 1 2

 ただしこれは相当雑然とした、tidyでないデータだ。
 よりtidyにするには、例えばrarity列に1~5が入っていて、nセット目のm回目にどのrarityのものが出たかというのが、各行に入っているようにする必要がある。
 つまり下記の状態にするのが次の目標になる。

name  times  rarity
smp1  x1  1
smp1  x2  2
smp1  x3  3
smp1  x4  2
smp1  x5  3
smp2  x1  4

今日はここまで。

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