ggplot2でviolin plotとdotplotの両方で可視化する
今回はこんな感じのグラフを描けるようになることを目標にします。
0. はじめに
第68回TokyoRは盛況に終わったようです。地方都市に住んでいる自分はなかなか参加できず ( ドタキャンして大変申し訳ありません ) 、運営のみなさんが流してくださったツイキャスやスライドなどを見て勉強しております。Togetterにもまとめられています。
さて、データの可視化の話題でgeom_violin
の話になった時に、@yutanihilationさんが呟いていたグラフが気になったのです。
geom_flat_violin()がちょっと前に話題でしたね。 https://t.co/EXeDYkmUqO #TokyoR
— Hiroaki Yutani (@yutannihilation) 2018年3月3日
Great figure! I was inspired to do a little playing around, with a helpful 'flat violin' geom from @drob. #rstats #iris #dataviz #ShowTheData pic.twitter.com/pUaZ1IH85a
— Joey Burant (@jbburant) 2018年2月20日
@mrunadonさんも同じグラフについて呟いていました。
https://t.co/DdSuwp2Rth
— MrUnadon (@MrUnadon) 2018年2月21日
これいいな、と思いました。 pic.twitter.com/Ix0mEYTvBK
dotplotとviolin plotを半分ずつ ( というかhistgram ) を併記していて、かなりデータに正直な可視化だと感激しました。自分はよくgeom_boxplotを使うのですが、可視化した後に生データを見て、グラフの印象との乖離に驚くことも多いです。このグラフに関して調べてみましたが、情報にたどり着けなかったので、slackでも躊躇なく聞いてみました。geom_flat_violinとgeom_dotplotの合わせ技で書けるようです。簡単ですがまとめてみました。
1. geom_flat_violinを導入する
geom_flat_violinのコードはこちらに置いてあります。
https://gist.github.com/dgrtwo/eb7750e74997891d7c20#file-geom_flat_violin-r
これをRで走らせると実はエラーになるのです。コメントにあるように
In case someone needs to find that comma... The mutate command has two end braces when it should just have one.
mutate(ymin = min(y), ymax = max(y), xmin = x, xmax = x + width / 2) ) # <---- Take this one out
line50の)
を削除すればgeom_flat_violinが機能として登録できるようになります。
2. geom_flat_violinを使ってみる
最後のexampleにあるコードを走らせてみるとグラフが書けます。
ggplot(diamonds, aes(x=cut, y=carat, fill=cut)) + geom_flat_violin()
教えてもらってはじめて気づいたのですが、geom_flat_violin
はviolin plotの右半分を描く機能なので、これにdotplotを足していく形になります。
3. geom_flat_violinにgeom_dotplotを合わせる
こちらのコードを参考に、geom_flat_violinにdotplotを重ねていきます。自力ではこのコードにたどり着けませんでしたが、@yutanihilationさんにslackで教えていただくことができました。躊躇せず質問してよかった笑
half_violin_with_raw_data.R · GitHub
ggplot(diamonds, aes(cut, carat, fill=cut)) + geom_flat_violin(scale = "count",trim = FALSE) + stat_summary(fun.data = mean_sdl, fun.args = list(mult = 1), geom = "pointrange", position = position_nudge(0.05))+ geom_dotplot(binaxis = "y", dotsize = 0.5, stackdir = "down", binwidth = 0.1, position = position_nudge(-0.025))
できましたが、あまりにnが大きすぎて、同じ値を取るサンプルが多いと、逆に見づらいグラフになってしまいますね…なのでirisを使った元のコードからグラフを作ります。
ggplot(data = iris, mapping = aes(x = Species, y = Sepal.Length, fill = Species)) + geom_flat_violin(scale = "count", trim = FALSE) + stat_summary(fun.data = mean_sdl, fun.args = list(mult = 1), geom = "pointrange", position = position_nudge(0.05)) + geom_dotplot(binaxis = "y", dotsize = 0.5, stackdir = "down", binwidth = 0.1, position = position_nudge(-0.025)) + theme(legend.position = "none") + labs(x = "Species", y = "Sepal length (cm)")
うん、美しい。状況に応じて活躍する機会がありそうな良いグラフですね。