ggplot2によるボックスプロット・箱ひげ図

日付;2022/07/16(土)
Rによるデータ解析(その5)

ボックスプロット(箱ひげ図)は、N数が10くらいあり、かつ、そのデータが正規分布していないような、というか、動物実験のデータなんかではとても便利なグラフである。また、エクセルでこのボックスプロットを作成しようとしてもなかなか難しい作図の一つであると思う。N=10くらいのデータでは、データを要約しようと思うと、平均値±標準偏差よりもデータの分布をより良く反映しているのではないかと思っている。

ボックスは、25パーセンタイル、中央値(50%パーセンタイル)、75パーセンタイルを示し、 ヒゲ部分(Whisker)の上下はIQR(InterQualtile Region)の1.5倍とされることが多い。もちろん、最大値と最小値がIQRの1.5倍より大きかったり少なかったりすると、それがヒゲ部分となる。

ここでは、ggplot2によるボックスプロットの作成方法を述べる。ただし、後述のように、個人的にはggplot2よりもbeeswarmというパッケージによるボックスプロットの方が好きである。その理由はbeeswarmの方が明らかに理解しやすいためだ。ggplot2は、なんとかというグラフィックの文法を元にして書かれているようだが、正直言って、それはRの流れっぽくない感じがする。一方のbeeswarmは、そのまんまRである。だから。

必要なライブラリ

ggplot2はtidyverseに入っているため、library(tidyverse)する。beeswarmはlibrary(beeswarm)する。

R
library(tidyverse)
library(beeswarm)

ggplot2によるボックスプロット

ボックスプロットの何が良いって、平均値だの標準偏差だのを計算する必要がない。例えば、薬剤、細胞の種類、日時といったグループ化が適切にされていればOKである。これらは一般的にデータの入力時に既に分類で付けられているだろうから、その場合はほぼ生データのまま作図に使用することができる。

尚、もしドットをばらつかせたかったら、geom_dotplot()のところあたりにjitterを加える関数を使えば良いのだと思う。なんかパッとデータが見つからなかったので、見つけたらまた書こうと思う。

R
ggplot(OriginalDataSet, aes(x = Drug_ID, y = Tumor)) +
geom_boxplot() +
geom_dotplot(binaxis = "y", stackdir = "centerwhole") +
theme_bw()

ggplot2によるボックスプロットに平均値を加える

上述では平均値とかを特に計算しなくてもすぐ作図できるから好きだとか言っていたが、だからといって平均値はどんなもんだったか知りたい場合もある。正直、そういうときって結果が理想的ではなかったりする場合が多いのだか、それも一行追加するだけである。

R
ggplot(OriginalDataSet, aes(x = Drug_ID, y = Tumor)) +
geom_boxplot() +
geom_dotplot(binaxis = "y", stackdir = "centerwhole") +
stat_summary(fun = "mean", colour = "red", size = 5, geom = "point") +
theme_bw()

beeswarmを使ったボックスプロット

なぜかbeeswarmを使ったほうが、理想的なボックスプロットを描ける気がしてならない。研究をしていても、こっちの方をよく使う。beeswarm自体はボックスプロットを描く関数ではなく、ドットプロットにジッターをいい感じに与えるための関数である。しかし、これは通常のボックスプロットと非常に相性がいい気がする。まずは以下のようにボックスプロットを描く。

R
par(lty = "solid", xaxs = "r")
bx.p <- boxplot(Tumor ~ Drug_ID,
        lty ="solid",
        lwd = 1,
        data = OriginalDataSet,
        outline = FALSE,
        col = c("Blue","Red"))

次にbeeswarmでジッターを付けたドットプロットを上述で書いたボックスプロットに重ねる。add=Tというヤツが、グラフをどんどん重ねる、という意味である。一応、これで完成である。

R
beeswarm(Tumor ~ Drug_ID,
                  data = OriginalDataSet,
                  method = "swarm",
                  spacing = 1.0,
                  add = T,
                  cex = 1.0,
                  pch = 16,
                  pwcol = NULL,
                  xlab = "",
                  ylab = "")

beeswarmによるボックスプロットに平均値を加える。

上記で書いた一般的なボックスプロットに平均値を重ねることもできる。それは、以下を加える。なんか、これは如何にもRって感じがする。

R
bx.p$stats[3, ] <- unclass(with(OriginalDataSet, by(Tumor, Drug_ID, FUN = mean)))
bxp(bx.p, 
        add=T, 
        boxfill="transparent", 
        medlty = 2, 
        medcol="black", 
        axes=F, 
        outpch = NA, 
        outlty="blank", 
        boxlty="blank", 
        whisklty="blank", 
        staplelty="blank")

これは完全に力技で、上記までに書いたボックスプロットに、平均値を書いた透明なボックスプロットを重ねるというものである。力技であるが、けっこうしっかりとデータの分布を要約してくれている気がする。それに、ここまですればレビューアーも満足するかもしれない。

beeswarmを使ってボックスプロットを描くときの重要なポイント;グラフを描く順番

通常のRのグラフィックでadd=Tを使うことで前のグラフに後に描くグラフを書き足していくとき、一番最初にはベタ塗りされたグラフを書き、その上にドットプロットを描く、というように順番を考える必要がある。例えば、最初にbeeswarmによるドットプロットを書いて、次にboxplot()を書いた場合、そのboxplot()の中で赤だの青だのの色でベタ塗りを指定している場合は、ベタ塗りでドットが上書きされてドットのないボックスプロットになってしまうので注意が必要である。