コラム: 箱ひげ図

Kenji Sato

2018/11/23

箱ひげ図(Box and whisker plot)の描き方について簡単に説明します。ggplot2 を使って,箱ひげ図を描きますので,tidyverse を読み込んでおきます。図を描くためのデータとして,正規乱数を用意しておきましょう。

library(tidyverse)
Y <- rnorm(200)
df <- tibble(Y)

ggplot(df) + geom_histogram(aes(x = Y))

箱ひげ図というのは次のような図です。

ggplot(df) + 
  geom_boxplot(aes(x = "", y = Y), width = 0.4) + 
  labs(x = "") 

次のような特徴があります。

データの整列と四分位数

箱ひげ図を手作業で描くために必要な前処理は,データを小さい順(あるいは大きい順)に並べることです。 そして,次のデータを調べます。

R ではこれらの数字を fivenum() 関数または quantile() 関数で求めることができます。

fivenum(Y)
## [1] -2.27192549 -0.50915180 -0.06176448  0.54389678  2.58195893
quantile(Y)
##          0%         25%         50%         75%        100% 
## -2.27192549 -0.50567207 -0.06176448  0.52737652  2.58195893

quantile() 関数は次のように任意の分位値を求めるために使うことができます。

quantile(Y, c(0.1, 0.35))
##        10%        35% 
## -1.1180365 -0.3316572

箱ひげ図の箱は

になるように描かれます。

IQR (Inter-Quartile Range)

次に,IQR (Inter-Quartile Range) を計算します。これは

\[ \text{IQR} = \text{第3四分位数} - \text{第1四分位数} \] で定義されます。定義どおりに計算するならば,

fivenum(Y)[4] - fivenum(Y)[2]
## [1] 1.053049

R には IQR() という関数があるので,そちらを使うのが標準的です。

IQR(Y)
## [1] 1.033049

この IQR が箱ひげ図の「ひげの長さ」を決めます。デフォルトでは

  • ひげの上端の最大値 = 第3四分位数 + 1.5 × IQR
  • ひげの下端の最小値 = 第1四分位数 - 1.5 × IQR

となっています。実際の上端・下端はデータで決まります。つまり,

  • 「第3四分位数 + 1.5 × IQR」を超えないデータのうち最大の値がひげの上端になり,
  • 「第1四分位数 - 1.5 × IQR」を下回らないデータのうち最小の値がひげの下端になります。

ggplot2 のデフォルトでは(Tukey の流儀にしたがって),

  • 「第3四分位数 + 1.5 × IQR」より大きいデータ
  • 「第1四分位数 - 1.5 × IQR」より小さいデータ

は外れ値 (outliers) として扱い,これらはひげではなく点で表示します。

箱ひげ図のカスタマイズ

geom_boxplot に対応した stat_boxplot を使うことでカスタマイズができます。次の例で分かるように,geom_boxplot() を使う代わりに stat_boxplot() を使うことができます。

ggplot(df) + 
  stat_boxplot(aes(x = "stat_boxplot", y = Y), geom = "boxplot", coef = 1.5) + 
  geom_boxplot(aes(x = "geom_boxplot", y = Y)) 

ひげの先端に横線を引きたい

https://stackoverflow.com/a/13003038

ggplot(df, aes(x = "", y = Y)) + 
  stat_boxplot(geom = "errorbar", width = 0.3) +   # ひげと横線を描写するコード
  geom_boxplot() 

外れ値もすべてひげの中に入れたい

高校の教科書ではこちらが紹介されています。stat_boxplot()coef = Inf を渡します。デフォルトでは coef = 1.5 ですが,これを無限に大きくするということです。

ggplot(df, aes(x = "", y = Y)) + 
  stat_boxplot(coef = Inf)

ひげの先端に横線を引くには,先程やったのと同様に stat_boxplotgeom = errorbar を渡します。

ggplot(df, aes(x = "", y = Y)) + 
  stat_boxplot(geom = "errorbar", coef = Inf, width = 0.3) +
  stat_boxplot(coef = Inf)