Note of Pediatric Surgery

腸内細菌、R、ときどき小児外科

ggplot2でviolin plotとdotplotの両方で可視化する

今回はこんな感じのグラフを描けるようになることを目標にします。

f:id:Razumall:20180304101441p:plain

0. はじめに

第68回TokyoRは盛況に終わったようです。地方都市に住んでいる自分はなかなか参加できず ( ドタキャンして大変申し訳ありません ) 、運営のみなさんが流してくださったツイキャスやスライドなどを見て勉強しております。Togetterにもまとめられています。

togetter.com

さて、データの可視化の話題でgeom_violinの話になった時に、@yutanihilationさんが呟いていたグラフが気になったのです。

@mrunadonさんも同じグラフについて呟いていました。

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()

f:id:Razumall:20180304101102p:plain

教えてもらってはじめて気づいたのですが、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

gist.github.com

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))

f:id:Razumall:20180304101436p:plain

できましたが、あまりに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)")

f:id:Razumall:20180304101441p:plain

うん、美しい。状況に応じて活躍する機会がありそうな良いグラフですね。