Mukku John Blog

取り組んでいること を つらつら と

ggplot2を使って、データ分布を要約する-4

R グラフィックス クックブック 18回目

ggplot2パッケージを利用して、データ分布を可視化していきます。

利用するデータ

2つのデータセットを使います。
1つ目:R: Old Faithful Geyser Data
間欠泉の噴出時間(eruptions)と次に噴出までの間隔(waiting)です。

> str(faithful)
'data.frame':	272 obs. of  2 variables:
 $ eruptions: num  3.6 1.8 3.33 2.28 4.53 ...
 $ waiting  : num  79 54 74 62 85 55 88 85 51 85 ...

> head(faithful)
  eruptions waiting
1     3.600      79
2     1.800      54
3     3.333      74
4     2.283      62
5     4.533      85
6     2.883      55

2つ目:

> str(heightweight)
'data.frame':	236 obs. of  5 variables:
 $ sex     : Factor w/ 2 levels "f","m": 1 1 1 1 1 1 1 1 1 1 ...
 $ ageYear : num  11.9 12.9 12.8 13.4 15.9 ...
 $ ageMonth: int  143 155 153 161 191 171 185 142 160 140 ...
 $ heightIn: num  56.3 62.3 63.3 59 62.5 62.5 59 56.5 62 53.8 ...
 $ weightLb: num  85 105 108 92 112 ...

> head(heightweight)
  sex ageYear ageMonth heightIn weightLb
1   f   11.92      143     56.3     85.0
2   f   12.92      155     62.3    105.0
3   f   12.75      153     63.3    108.0
4   f   13.42      161     59.0     92.0
5   f   15.92      191     62.5    112.5
6   f   14.25      171     62.5    112.0

ドットプロット

ドットプロット - Wikipedia
ヒストグラムと同じです。データをビン詰めして、ドットで積み上げています。
ドットプロットを作成するには、geom_dotplot()を使います。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot()

f:id:MukkuJohn:20160919092955p:plain

他グラフと同様に、塗りつぶしはfill、線の色は、colourを指定します。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(fill="lightblue",colour="grey60") +
  theme_bw()

f:id:MukkuJohn:20160919093840p:plain

ビンの幅は、デフォルトでデータ範囲の1/30となっています。
ビンの幅を変更するには、binwidthを指定します。

#eruptionsの範囲を取って、差を30で割る
binSize <- diff(range(faithful$eruptions)) / 30

#binwidth引数を指定する
#データ範囲を30で割ったビン幅なので、デフォルトと同じ
ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(binwidth = binSize,
               fill="lightblue",colour="grey60") +
  theme_bw()

f:id:MukkuJohn:20160919093755p:plain

このドットプロットですが、y軸の目盛りがおかしいです。
本によると、ggplot2の技術的な問題らしく、
y軸を表示させない回避策を取っています。(回避策なのか?)

おかしいスケールのy軸を消します。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(binwidth = binSize,
               fill="lightblue",colour="grey60") +
  theme_bw() + 
  scale_y_continuous(breaks = NULL) +   #目盛りを除く
  theme(axis.title.y = element_blank()) #軸ラベルを除く

f:id:MukkuJohn:20160919094717p:plain

さらに、グラフをよく見ると、x軸に対してドットが等間隔でないです。
妙に横とくっついているドットもあれば、離れているドットもあります。

これは、ビンを決めるアルゴリズムによって決まります。
デフォルトでは、dotdensityになっています。*1
変更するためには、method引数を指定します。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(binwidth = binSize,
               fill="lightblue",colour="grey60",
               method = "histodot") + #ヒストグラムと同じ
  theme_bw() + 
  scale_y_continuous(breaks = NULL) +
  theme(axis.title.y = element_blank())

f:id:MukkuJohn:20160919095737p:plain

x軸に対して等間隔にしましたが、y軸に対してセンタリングすることもできます。
stackdir引数を指定します。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(binwidth = binSize,
               fill="lightblue",colour="grey60",
               method = "histodot",
               stackdir = "center") + #y軸に対して中央揃え
  theme_bw()

f:id:MukkuJohn:20160919100226p:plain

上のグラフは、y軸に対してセンタリングされています。
そのため、ドットが奇数の列と偶数の列では、y軸に対してずれています。
奇数/偶数の列でそろえる場合は、centerwholeを指定します。

ggplot(faithful, aes(x=eruptions)) +
  geom_dotplot(binwidth = binSize,
               fill="lightblue",colour="grey60",
               method = "histodot",
               stackdir = "centerwhole") + #奇数/偶数の列を揃える
  theme_bw()

f:id:MukkuJohn:20160919100623p:plain


今までは、x軸でビンを区切りy軸方向に積み上げてきましたが、
ドットプロットは、y軸でビンを区切りx軸方向に積み上げることができます。
(y軸でビンを区切ることで、おかしい目盛りがでないです)

グループ化したドットプロットで、x軸方向にビン積み上げをしてみます。

グループ化したドットプロット

グループ化したドットプロットを作るために、
x軸に離散値を、y軸に連続値をマッピングして、binaxis引数を指定します。

ggplot(heightweight, aes(x=sex, y=heightIn)) +
  geom_dotplot(binaxis = "y", binwidth = .5, stackdir = "center",
               fill="lightblue", colour="grey60")

f:id:MukkuJohn:20160919102203p:plain

上のグラフは、y軸でセンタリングしていますが、
下のグラフを見ると、理由が分かると思います。
(y軸でセンタリングしないと、まとめる意味が…)
f:id:MukkuJohn:20160919102546p:plain


このy軸方向に積み上げた、ドットプロットですが
箱ひげ図と重ねてみるのが慣例っぽいです。

ggplot(heightweight, aes(x=sex,y =heightIn)) +
  geom_boxplot(outliner.colour=NA,width=.4)+
  geom_dotplot(binaxis = "y",binwidth = .5,stackdir = "center",
               fill="lightblue",alpha=.5,colour="grey60")

f:id:MukkuJohn:20160919103416p:plain

ドットプロットも箱ひげ図も観測値ですが、両方あることで納得感が増すかな。

さすがに、バイオリンプロットまで重ねると、色の調整が大変です。

ggplot(heightweight, aes(x=sex,y =heightIn)) +
  geom_boxplot(outliner.colour=NA,width=.4)+
  geom_violin(fill="lightgreen",alpha=.2,trim=FALSE)+
  geom_dotplot(binaxis = "y",binwidth = .5,stackdir = "center",
               fill="black",alpha=.5,colour="grey60")

f:id:MukkuJohn:20160919103817p:plain


上記の様に重ねてみる場合は、それぞれのグラフをx軸方向にずらすと良いです。

ggplot(heightweight, aes(x=sex,y=heightIn)) +
  geom_violin(aes(x=as.numeric(sex) + .25, group=sex), width=.5,fill="blue", 
              alpha=.2,trim=FALSE) +
  geom_boxplot(aes(x=as.numeric(sex) + .25, group=sex),width=.25, fill="cornsilk")+
  geom_dotplot(aes(x=as.numeric(sex) - .3, group=sex),binaxis = "y",
               binwidth=.5,stackdir="center")+
  scale_x_continuous(breaks=1:nlevels(heightweight$sex),
                     labels=levels(heightweight$sex))

f:id:MukkuJohn:20160919104421p:plain

次回は、2次元の密度推定をプロットし、
データ分布の最後にしたいと思います。