tidyrのmulti-gatherの未来
(これはtidyポエム Advent Calendar 2017 - Adventar 6日目の記事です)
こんなIssueがあります。
multi-gatherというのは何かというと、例えば、こういうデータを
testA_score | testA_type | testB_score | testB_type |
---|---|---|---|
100 | x | 90 | y |
80 | y | 10 | z |
44 | z | 19 | z |
44 | x | 77 | x |
こう変形するようなやつです。
test | score | type |
---|---|---|
testA | 100 | x |
testB | 90 | y |
testA | 80 | y |
testB | 10 | z |
testA | 44 | z |
testB | 19 | z |
testA | 44 | x |
testB | 77 | x |
列名にtestA
かtestB
(テストの種類)、値がscore
かtype
か(テストの種類)という複数の情報が含まれているのをtidyな形に変形しています。
これは今のところ、いい感じにやる方法がありません。だいたい同じことは以下のようにすればできます。
library(tidyr) library(tibble) library(dplyr, warn.conflicts=FALSE) tribble( ~testA_score, ~testA_type, ~testB_score, ~testB_type, 100, "x", 90, "y", 80, "y", 10, "z", 44, "z", 19, "z", 44, "x", 77, "x" ) %>% # あとでspreadするときに行を一意に識別するキーに使う。これがエラーになる。 rowid_to_column(var = "rowid") %>% # とりあえずいったんすべての列をgather()する gather("key", "value", -rowid) %>% # "testA_score"を_で切り離して"testA"と"score"にする separate(key, into = c("test", "column"), sep = "_") %>% # scoreとtypeは列になるべきものなのでspreadする spread(column, value) %>% # spreadしてしまったらrowidはもう不要なので消す select(-rowid) #> # A tibble: 8 x 3 #> test score type #> * <chr> <chr> <chr> #> 1 testA 100 x #> 2 testB 90 y #> 3 testA 80 y #> 4 testB 10 z #> 5 testA 44 z #> 6 testB 19 z #> 7 testA 44 x #> 8 testB 77 x
しかし、気づいたかもしれませんが、score
がcharacterになってしまっています。これは、このやり方だと値の型が違うscore
もtype
もいったん一緒の列にgather()
しないといけないためです。本来はscore
とtype
を別々に扱う処理が望ましいです。これが、multi-gatherです。
しかし、上のIssueは止まったままです。これはなぜかというと、ひとつには設計に時間をかけていることですが、もうひとつには、
x %>% gather(Race, colnames = multikey("(gender)_(film)"), value = "words")
みたいに書くときに、正規表現のnamed capture groupが使えないと困る、ということのようです(↑自体はnamed capture groupとして使える正規表現じゃないので、もうちょっと仕組みが必要そうですけど)。
I wonder if there's some way to hack in named groups support to stringi.
(https://github.com/tidyverse/tidyr/issues/150#issuecomment-328574220)
named capture groupはstringiの領分で、issueとしては積まれているんですが、止まったままです。
どうもICUのバージョンを上げる必要があるらしいですが、色んなOSをサポートする都合上そんな気軽にも上げられない感じらしいです。
Update to ICU 59 needs C++11. Solaris can stay ICU55. Need both icudt55 and icudt59 + separate sources
おのれSolaris...
ということで未来はなかなか見えないですが、はやく入ってほしい機能です。