Mukku John Blog

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

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

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

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

利用するデータ

このデータセットを使います。
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次元データの密度推定

前回の記事まで計4回は、1個の要素について、観測値や推定値をプロットしてきました。
ここでは、2個の要素をまとめます。

x軸にeruptions、y軸にwaitingをマッピングした散布図と、
カーネル密度推定の曲線*1をプロットします。

2次元のカーネル密度推定は、stat_density2d()を使います。

ggplot(faithful, aes(x=eruptions, y=waiting)) +
  geom_point() +
  geom_density2d()

f:id:MukkuJohn:20160920201807p:plain

この密度曲線ですが、高さを色にマッピングすることができます。

ggplot(faithful, aes(x=eruptions, y=waiting)) +
  geom_point() +
  geom_density2d(aes(colour=..level..))

f:id:MukkuJohn:20160920202003p:plain
(なんかわかりづらいですね。)


可視化には、塗りつぶしたり、透過して表示したりできます。

ggplot(faithful, aes(x=eruptions, y=waiting)) +
  stat_density2d(aes(fill=..density..),
                 geom = "raster",contour = FALSE)

f:id:MukkuJohn:20160920203137p:plain

ggplot(faithful, aes(x=eruptions, y=waiting)) +
  geom_point() +
  stat_density2d(aes(alpha=..density..),
                 geom = "tile",contour = FALSE)

f:id:MukkuJohn:20160920203145p:plain


1次元の密度推定と同じように、平滑化の帯域幅を指定できます。
2次元なので、x軸とy軸に対する帯域幅ベクトルを指定します。

ggplot(faithful, aes(x=eruptions, y=waiting)) +
  stat_density2d(aes(fill=..density..),
                 geom = "raster",contour = FALSE,
                 h=c(.5,5))

f:id:MukkuJohn:20160920203339p:plain

…う~ん、なんだかなぁという感じです。。。

データ分布のまとめ

今回含め、全5回、データ分布を可視化することをしてきました。

観測値系

データの観測値を可視化するグラフは、この3つです。

  • ヒストグラムgeom_histogram()
  • 箱ひげ図:geom_boxplot()
  • ドットプロット:geom_dotplot

ヒストグラムとドットプロットは、ビン詰め系です。
ビン詰め系は、binwidth引数で、ビンの幅を指定できます。

ヒストグラムは、x軸に連続値を取りますが、
箱ひげ図とドットプロットは、x軸に離散値を取りました。

推定値系

推定値の曲線は、この2つです。

  • 密度曲線:geom_density() / geom_line(stat="density")
  • バイオリンプロット:geom_violin()

グラフは分かれていますが、密度曲線を左右対称 = バイオリンプロット です。
どちらも、adjust引数で、平滑化の帯域幅を指定できます。

観測値 + 推定値の組み合わせ

x軸に連続値を取るグラフか否かで分かれます。

ヒストグラムと密度曲線を、重ねてプロットする時は、
y軸のスケールを、密度曲線側に合わせる必要があります。

どのグラフもグループ化はできますが、x軸が連続値のモノは、
色分けよりも、ファセットグリッドを使った方が見やすいです。


次回からは、グラフ内に注釈を入れる方法を扱っていきます。

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次元の密度推定をプロットし、
データ分布の最後にしたいと思います。

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

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

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

利用するデータ

R: Risk Factors Associated with Low Infant Birth Weightデータセットを使います。
乳幼児の出生時の体重に関わるリスク要因のデータです。

> str(birthwt)
'data.frame':	189 obs. of  10 variables:
 $ low  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ age  : int  19 33 20 21 18 21 22 17 29 26 ...
 $ lwt  : int  182 155 105 108 107 124 118 103 123 113 ...
 $ race : int  2 3 1 1 1 3 1 3 1 1 ...
 $ smoke: int  0 0 1 1 1 0 0 0 1 1 ...
 $ ptl  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ht   : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ui   : int  1 0 0 1 1 0 0 0 0 0 ...
 $ ftv  : int  0 3 1 2 0 0 1 1 1 0 ...
 $ bwt  : int  2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...

> head(birthwt)
   low age lwt race smoke ptl ht ui ftv  bwt
85   0  19 182    2     0   0  0  1   0 2523
86   0  33 155    3     0   0  0  0   3 2551
87   0  20 105    1     1   0  0  0   1 2557
88   0  21 108    1     1   0  0  1   2 2594
89   0  18 107    1     1   0  0  1   0 2600
91   0  21 124    3     0   0  0  0   0 2622

race値を使いますので、ファクタに変換して、ラベル付けします。

birthwt2 <- birthwt
birthwt2$race <- factor(birthwt2$race)
birthwt2$race <- revalue(birthwt2$race,c("1"="white","2"="black","3"="other"))

箱ひげ図

箱ひげ図 - Wikipedia *1
箱ひげ図を作成するには、geom_boxplot()を使います。
x軸に離散値を、y軸に連続値をマッピングします。

ggplot(birthwt2, aes(x=race, y=bwt)) + 
  geom_boxplot()

f:id:MukkuJohn:20160918094131p:plain

他のグラフと同様に、枠線:colour/塗りつぶし:fillで変更できます。

ggplot(birthwt2, aes(x=race, y=bwt)) + 
  geom_boxplot(colour="grey60",fill="cornsilk") +
  theme_bw()

f:id:MukkuJohn:20160918094850p:plain


箱の幅を変更するためには、widthを指定します。

ggplot(birthwt2, aes(x=race, y=bwt)) + 
  geom_boxplot(width=.5)

f:id:MukkuJohn:20160918095022p:plain


外れ値のマークは、大きさと形を指定できます。
outlierを指定します。

ggplot(birthwt2, aes(x=race, y=bwt)) + 
  geom_boxplot(width=.5,
               outlier.size = 4,
               outlier.shape = 21,
               outlier.colour = "red")

f:id:MukkuJohn:20160918095304p:plain


ノッチ*2を追加するには、notchを指定します。

#notchのデフォルト値はFALSE
ggplot(birthwt2, aes(x=race,y=bwt)) +
  geom_boxplot(notch = TRUE, colour="grey60",fill="cornsilk") +
  theme_bw()

f:id:MukkuJohn:20160918100130p:plain


平均値を追加するためには、stat_summary()を追加します。

ggplot(birthwt2, aes(x=race,y=bwt)) +
  geom_boxplot(notch = TRUE, colour="grey60",fill="cornsilk") +
  stat_summary(fun.y="mean",geom="point") +
  theme_bw()

f:id:MukkuJohn:20160918100429p:plain

平均値を表すマークは、大きさ、形、色/塗りつぶしが指定できます。

ggplot(birthwt2, aes(x=race,y=bwt)) +
  geom_boxplot(notch = TRUE, colour="grey60",fill="cornsilk") +
  stat_summary(fun.y="mean",geom="point", size=3, shape=22, fill="lightblue",colour="blue") +
  theme_bw()

f:id:MukkuJohn:20160918100736p:plain

バイオリンプロット

密度曲線*3を左右対称でプロットしたモノです。

この密度曲線をグリッドで分けることなく、確認できます。
f:id:MukkuJohn:20160918103117p:plain

バイオリンプロットを使うためには、geom_violin()を使います。

ggplot(birthwt2,aes(x=race,y=bwt)) +
  geom_violin() 

f:id:MukkuJohn:20160918101845p:plain


線の色や、塗りつぶし、透明度は他のグラフと同じ指定です。

ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60",fill="blue",alpha=.2) +
  theme_bw()

f:id:MukkuJohn:20160918102104p:plain

上下端が切れてしまっています。
デフォルトでは、最大値/最小値で、平らにカットされてしまいます。
平らにカットしない場合は、trimを指定します。

ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60", fill="blue", alpha=.2,
              trim=FALSE) +
  theme_bw()

f:id:MukkuJohn:20160918113053p:plain


バイオリンプロットの塗りつぶされている面積ですが、
デフォルトでは、各バイオリンの面積が等しくになっています。

面積を観測値の数と等しくするためには、scaleを指定します。

ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60", fill="blue", alpha=.2,
              trim=FALSE,
              scale="count") +
  theme_bw()

f:id:MukkuJohn:20160918113342p:plain


繰り返しになりますが、
バイオリンプロットは、密度曲線を左右対称にプロットしたモノですので、
密度曲線と同じように、平滑化できます。

平滑化の指定は、密度曲線と同じ、adjustを指定します。

ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60", fill="blue", alpha=.2,
              trim=FALSE,
              scale="count",
              adjust=2) +
  theme_bw()

f:id:MukkuJohn:20160918113556p:plain

ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60", fill="blue", alpha=.2,
              trim=FALSE,
              scale="count",
              adjust=.5) +
  theme_bw()

f:id:MukkuJohn:20160918113653p:plain


ヒストグラム-密度曲線と同様に、箱ひげ図-バイオプロットと重ねることで
観測値の分布(=箱ひげ図)推定値の分布(=バイオリンプロット)をまとめます。

#バイオリンプロット → 箱ひげ図 → 中央値マーク
ggplot(birthwt2,aes(x=race,y=bwt))+
  geom_violin(colour="grey60", fill="blue", alpha=.2,
              trim=FALSE,
              scale="count") +
  geom_boxplot(width=.2,fill="cornsilk",outlier.colour = NA) +
  stat_summary(fun.y=median,geom="point",fill="green",
               shape=21,size=3) +
  theme_bw()

f:id:MukkuJohn:20160918114000p:plain


次回は、データポイントを表示するドットプロットを作成します。

*1:箱ひげ図の読み方は、こちら mukkujohn.hatenablog.com

*2:中央値の95%信頼区間

*3:密度曲線については、この記事。mukkujohn.hatenablog.com

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

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

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つ目:
R: Risk Factors Associated with Low Infant Birth Weight
乳幼児の出生時の体重に関わるリスク要因のデータです。

> str(birthwt)
'data.frame':	189 obs. of  10 variables:
 $ low  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ age  : int  19 33 20 21 18 21 22 17 29 26 ...
 $ lwt  : int  182 155 105 108 107 124 118 103 123 113 ...
 $ race : int  2 3 1 1 1 3 1 3 1 1 ...
 $ smoke: int  0 0 1 1 1 0 0 0 1 1 ...
 $ ptl  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ht   : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ui   : int  1 0 0 1 1 0 0 0 0 0 ...
 $ ftv  : int  0 3 1 2 0 0 1 1 1 0 ...
 $ bwt  : int  2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...

> head(birthwt)
   low age lwt race smoke ptl ht ui ftv  bwt
85   0  19 182    2     0   0  0  1   0 2523
86   0  33 155    3     0   0  0  0   3 2551
87   0  20 105    1     1   0  0  0   1 2557
88   0  21 108    1     1   0  0  1   2 2594
89   0  18 107    1     1   0  0  1   0 2600
91   0  21 124    3     0   0  0  0   0 2622

密度曲線

標本データに基づいた母集団の分布の推定の曲線です。
密度曲線を表示するには、geom_density()を使います。

ggplot(faithful, aes(x=waiting)) + 
  geom_density()

f:id:MukkuJohn:20160917132923p:plain

ヒストグラムと比較してみると、分布の曲線になっていることが
イメージできます。
f:id:MukkuJohn:20160917133003p:plain

曲線の下部や横の線の輪郭線が邪魔な場合は、
geom_line(stat="density")を使います。*1

ggplot(faithful, aes(x=waiting)) + 
  geom_line(stat = "density") + 
  expand_limits(y=0)

f:id:MukkuJohn:20160917133712p:plain


x軸にマッピングする項目は、
データフレームの1列か、1つのベクトルである必要があります。

ヒストグラムと同様*2に、
データフレームでない項目は、ggplot()の引数に、NULLとベクトルを指定します。

w <- faithful$waiting
ggplot(NULL,aes(x=w)) + geom_density()

f:id:MukkuJohn:20160917134103p:plain


平滑化帯域幅によって、曲線が滑らかになったり、粗く(?)なったりします。
この帯域幅は、adjustを指定することで変更できます。

#帯域幅のデフォルト値は、1
ggplot(faithful, aes(x=waiting)) +
  geom_line(stat = "density", adjust=.25, colour="red") +
  geom_line(stat = "density") +
  geom_line(stat = "density", adjust=2, colour="blue")

f:id:MukkuJohn:20160917134521p:plain

上のグラフは、曲線の端が切れてしまっています。
曲線の端が切れている場合は、x軸の範囲を指定します。

上のグラフ + xlim(35,105)

f:id:MukkuJohn:20160917134705p:plain

fillを指定する事で、塗りつぶしができます。

ggplot(faithful, aes(x=waiting)) +
  geom_density(fill="blue",alpha=.2)+
  xlim(35,105)

f:id:MukkuJohn:20160917134909p:plain


密度曲線は、これらの考察が必要です。

  • 平滑化されすぎていないか
  • 密度曲線がデータの最適なモデルになっていないのか
  • データのサンプルサイズが小さくないか

ヒストグラムと重ねることで
推定した分布(=密度曲線)と、観測値の分布(=ヒストグラム
合わせて確認・考察することができます。

ただ密度曲線のy軸と、ヒストグラムのy軸のスケールが合いません。
(上記の密度曲線のy軸を確認してみてください。)

そこで、ヒストグラムを密度曲線に合わせてスケールダウンすることが必要です。

#y=..density..でヒストグラムをスケールダウンしています。
ggplot(faithful,aes(x=waiting,y=..density..))+
  geom_histogram(fill="cornsilk",colour="grey60",size=.2)+
  geom_density()+
  xlim(35,105)

f:id:MukkuJohn:20160917135927p:plain

グループ化した密度曲線

前回の記事*3で、グループ化したヒストグラムを扱いました。
当然ながら、推定した分布である密度曲線も、グループ化して扱います。

ヒストグラムのグループ化と同様に、グループにマッピングする項目は
ファクターでないといけません。

#前記事と同様に、ファクタに変換しラベル付けもしておきます。
library(plyr)
birthwt1 <- birthwt
birthwt1$smoke <- factor(birthwt1$smoke)
birthwt1$smoke <- revalue(birthwt1$smoke,c("0"="No Smoke","1"="Smoke"))

グループ化は、colourfillマッピングします。

#colourにマッピングします
ggplot(birthwt1,aes(x=bwt,colour=smoke)) + 
  geom_density()

f:id:MukkuJohn:20160917140941p:plain

#fillにマッピングします
#塗りつぶしが重なるため、透明度を指定します
ggplot(birthwt1,aes(x=bwt,fill=smoke)) + 
  geom_density(alpha=.3)

f:id:MukkuJohn:20160917141052p:plain


ファセットグリッドを使って、グループ化することもできます。

ggplot(birthwt1,aes(x=bwt)) +
  geom_density() +
  facet_grid(smoke ~ .)

f:id:MukkuJohn:20160917141200p:plain

ファセットグリッドを使うことで、グラフごとに
ヒストグラムと重ねることができます。

ggplot(birthwt1,aes(x=bwt, y=..density..)) +
  geom_histogram(binwidth=200,fill="cornsilk",colour="grey60",size=.2)+
  geom_density()+
  facet_grid(smoke ~ .)

f:id:MukkuJohn:20160917141313p:plain

頻度の折れ線

頻度の折れ線とは、観測値の頻度を表す線です。
つまるところ、ヒストグラムの棒が、線になっているだけです。

geom_freqpoly()を使います。

ggplot(faithful, aes(x=waiting)) + geom_freqpoly()

f:id:MukkuJohn:20160917141721p:plain

ヒストグラムと同じなので、ビンの幅を指定できます。

ggplot(faithful,aes(x=waiting)) + 
  geom_freqpoly(binwidth=4) + theme_bw()

f:id:MukkuJohn:20160917141819p:plain

もちろんヒストグラムと重ねて表示できます。

ggplot(faithful,aes(x=waiting)) +
  geom_histogram(fill="cornsilk",colour="grey60") +
  geom_freqpoly() + 
  theme_bw()

f:id:MukkuJohn:20160917142017p:plain

次回は、箱ひげ図を扱います。

*1:積み上げ面グラフの輪郭線を表示させない手法と同じです。 mukkujohn.hatenablog.com

*2:ヒストグラム作成記事はこちら。 mukkujohn.hatenablog.com

*3:脚注2と同じ記事です。

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

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

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つ目:
R: Risk Factors Associated with Low Infant Birth Weight
乳幼児の出生時の体重に関わるリスク要因のデータです。

> str(birthwt)
'data.frame':	189 obs. of  10 variables:
 $ low  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ age  : int  19 33 20 21 18 21 22 17 29 26 ...
 $ lwt  : int  182 155 105 108 107 124 118 103 123 113 ...
 $ race : int  2 3 1 1 1 3 1 3 1 1 ...
 $ smoke: int  0 0 1 1 1 0 0 0 1 1 ...
 $ ptl  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ht   : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ui   : int  1 0 0 1 1 0 0 0 0 0 ...
 $ ftv  : int  0 3 1 2 0 0 1 1 1 0 ...
 $ bwt  : int  2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...

> head(birthwt)
   low age lwt race smoke ptl ht ui ftv  bwt
85   0  19 182    2     0   0  0  1   0 2523
86   0  33 155    3     0   0  0  0   3 2551
87   0  20 105    1     1   0  0  0   1 2557
88   0  21 108    1     1   0  0  1   2 2594
89   0  18 107    1     1   0  0  1   0 2600
91   0  21 124    3     0   0  0  0   0 2622

ヒストグラム

ヒストグラム - Wikipedia
faithfulデータセットを使います。
ヒストグラムを作成するには、geom_histogram()を使います。

x軸に、waiting列をマッピングします。

ggplot(faithful, aes(x=waiting)) + geom_histogram()

f:id:MukkuJohn:20160914220416p:plain

x軸にマッピングする項目は、
データフレームの1列か、1つのベクトルである必要があります。


データフレームでない項目は、ggplot()の引数に、NULLとベクトルを指定します。

w <- faithful$waiting
#最初のグラフと同じ結果になります。
ggplot(NULL,aes(x=w)) + geom_histogram()

f:id:MukkuJohn:20160914220731p:plain


デフォルトは30のビン*1に分かれています。
変更するためには、geom_histogram()の引数のbinwidthを指定します。

#ビンの幅を5に設定する
ggplot(faithful, aes(x=waiting)) +
  geom_histogram(binwidth=5, fill="white", colour="black")

f:id:MukkuJohn:20160914221337p:plain

#ビンの数を15にする
binSize <- diff(range(faithful$waiting)) / 15
ggplot(faithful, aes(x=waiting)) +
  geom_histogram(binwidth=binSize, fill="white", colour="black")

f:id:MukkuJohn:20160914221447p:plain


ヒストグラムは、ビンの幅や数、また、データの境界によって見え方が変わります。

h <- ggplot(faithful, aes(x=waiting))
#ビンの幅を8で、x値の最小値を31から始める
#31 -> 39 -> 47 -> …
h + geom_histogram(binwidth=8, fill="white", colour="black", origin=31)

f:id:MukkuJohn:20160914221746p:plain

#ビンの幅を8で、x値の最小値を35から始める
#35 -> 43 -> 51 -> …
h + geom_histogram(binwidth=8, fill="white", colour="black", origin=35)

f:id:MukkuJohn:20160914221835p:plain

同じビンの幅ですが、どこから開始するかで大きく見え方が変わりました。
うまいこと分布を確認ためには、ビンの幅や境界を模索する必要があるようです。

グループ化したヒストグラム

birthwtデータセットを使います。
グループ化には、ファセットグリッドを使います。

ggplot(birthwt,aes(x=bwt)) + 
  geom_histogram(fill="white", colour="black") +
  facet_grid(smoke ~ .)

f:id:MukkuJohn:20160914222732p:plain

ファセットの指定に、smokeを指定しましたが、データは、01で表現されています。
そのため、ファセットのラベルも0と1になっています。

ラベル名を付与するには、ファクタにする必要があります。

#バックアップ
birthwt1 <- birthwt
#ファクタに変換
birthwt1$smoke <- factor(birthwt1$smoke)
#ファクタのラベルを付ける関数を使うため
library(plyr)
#ファクタのラベル付け
birthwt1$smoke <- revalue(birthwt1$smoke,c("0"="No Smoke","1"="Smoke"))

ファクタに変換後、再度同じコードでプロットします。

ggplot(birthwt1,aes(x=bwt)) + 
  geom_histogram(fill="white", colour="black") +
  facet_grid(smoke ~ .)

f:id:MukkuJohn:20160914223245p:plain


ファセットグリッドでのグループ化は、y軸のスケールは全て同じになります。
y軸が同じスケールだと、分布を確認するのがつらい場合があります。
race列でグループ化します。

ggplot(birthwt, aes(x=bwt)) + 
  geom_histogram(fill="white",colour="black") +
  facet_grid(race ~ .)

f:id:MukkuJohn:20160914223615p:plain

真ん中のrace=2のヒストグラムは、分布が分からないですね。

それぞれのヒストグラムで、y軸スケールを独立させるには、
facet_grid()のscales引数にfreeを指定します。

ggplot(birthwt, aes(x=bwt)) + 
  geom_histogram(fill="white",colour="black") +
  facet_grid(race ~ ., scales = "free")

f:id:MukkuJohn:20160914223840p:plain

他のグループ化の方法として、ヒストグラム自体を重ねて表示する方法があります。
smokeでグループ化します。

ggplot(birthwt1, aes(x=bwt,fill=smoke)) +
  geom_histogram(position = "identity", alpha=0.4)

f:id:MukkuJohn:20160914223940p:plain

raceでグループ化します。

ggplot(birthwt1, aes(x=bwt,fill=race)) +
  geom_histogram(position = "identity", alpha=0.4)

f:id:MukkuJohn:20160914224442p:plain

ヒストグラムを重ねて表示するためには、fillに指定する項目が
ファクタであることが条件になります。

次回は、密度曲線を扱います。

*1:任意に区切った区間。この本が分かりやすい。 mukkujohn.hatenablog.com

Power BIで、散布図を作ってみる

ggplot2で折れ線グラフを作成した時と、同じデータセットを使って、
Power BIで、どのような散布図が作れるかを試します。(散布図ムズィ)
mukkujohn.hatenablog.com

散布図

こちらのデータセットを使います。

> head(heightweight[, c("ageYear","heightIn","sex","weightLb")])
  ageYear heightIn sex weightLb
1   11.92     56.3   f     85.0
2   12.92     62.3   f    105.0
3   12.75     63.3   f    108.0
4   13.42     59.0   f     92.0
5   15.92     62.5   f    112.5
6   14.25     62.5   f    112.0

> str(heightweight[, c("ageYear","heightIn","sex","weightLb")])
'data.frame':	236 obs. of  4 variables:
 $ ageYear : num  11.9 12.9 12.8 13.4 15.9 ...
 $ heightIn: num  56.3 62.3 63.3 59 62.5 62.5 59 56.5 62 53.8 ...
 $ sex     : Factor w/ 2 levels "f","m": 1 1 1 1 1 1 1 1 1 1 ...
 $ weightLb: num  85 105 108 92 112 ...

x軸にageYearを、y軸にheightInをマッピングします。
f:id:MukkuJohn:20160912221029p:plain
!?
なんか点が1つなんですが、、、
なんかageYearとheightInが足されているようなんですが、、、

素直にチュートリアル見ました。チュートリアル: Power BI の散布図とバブル チャート | Microsoft Power BI
プロットする点のデータが一意である必要があるとのことなので、
インデックス列を追加し、詳細に設定してみました。
f:id:MukkuJohn:20160912221351p:plain
無事、作れました。

変更できる書式は、こんなところです。
f:id:MukkuJohn:20160912222713p:plain

特筆する部分は、これらでしょうか。

  • データの色
  • カテゴリラベル
  • フィルポイント

まず、データの色ですが、詳細に指定したデータ毎に色が付けれます。
f:id:MukkuJohn:20160912223004p:plain

このグラフですと、インデックス値ごとに、色が付けれるのですが、
どのポイントが、どのインデックス値か分からないので、設定しません。
この機能はいったい、、、


カテゴリラベルと、フィルポイントは下の図のとおりです。
f:id:MukkuJohn:20160912223210p:plain


凡例にsexを設定してみます。
f:id:MukkuJohn:20160912223426p:plain


さきほどのデータの色ですが、凡例ごとに指定できるようになりました。
f:id:MukkuJohn:20160912223455p:plain


分析部分ですが、他のグラフと比較して、追加できる線が多いです。
f:id:MukkuJohn:20160912223659p:plain


まず、傾向線ですが、全てのデータポイントを統合した傾向線
凡例ごとの傾向線をプロットすることができます。
f:id:MukkuJohn:20160912223933p:plain
f:id:MukkuJohn:20160912224010p:plain
線形回帰かな

その他の線は、x軸かy軸のどちらの軸に対する線かを選びます。
f:id:MukkuJohn:20160912224630p:plain
画像は、下3つの線を追加しています。

  • ageYearの最小値(黒線)
  • heightInの平均値(黄色線)
  • ageYearの中央値(緑線)

バブルチャート

点にサイズを持たせてみます。サイズに、別の項目を設定するだけです。
f:id:MukkuJohn:20160912230114p:plain
ageYear < 12 & heightIn < 56 とフィルターしています。
フィルターすると、分析線も再計算されていますね。

Power BIでは、点の大きさがデータの大きさに比例しているっぽいです。

オーバープロット

大量のデータを、プロットしてみます。

こちらのデータを使います。53940個のデータがあります。

> head(diamonds[ , c("carat", "price")])
  carat price
1  0.23   326
2  0.21   326
3  0.23   327
4  0.29   334
5  0.31   335
6  0.24   336

> str(diamonds[ , c("carat", "price")])
'data.frame':	53940 obs. of  2 variables:
 $ carat: num  0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
 $ price: int  326 326 327 334 335 336 336 337 337 338 ...


なんか左上に!マークが表示されています。
f:id:MukkuJohn:20160912230427p:plain

クリックすると、悲しいメッセージが、、、。
f:id:MukkuJohn:20160912230518p:plain

何個プロットされているのだろうと、書式 -> データの色を確認してみました。
f:id:MukkuJohn:20160912231359p:plain
なんか、文句言いながらも、全てのデータをプロットしている雰囲気が出てます。
(ためしにデータの色を変更しようとしたら、ブラウザが固まったので諦めました。)

Rのように、ビン詰めなどできないので、データポイントが多い場合は、
フィルターするしかないでしょうね。


次回からは、Rに戻り、データの分布が確認できるグラフを作成していきます。

Power BIで、折れ線グラフを作ってみる-2

ggplot2で折れ線グラフを作成した時と、同じデータセットを使って、
Power BIで、どのような折れ線グラフが作れるかを試します。
mukkujohn.hatenablog.com

積み上げ面グラフ

こちらのデータセットを使います。

> head(uspopage)
  Year AgeGroup Thousands
1 1900       <5      9181
2 1900     5-14     16966
3 1900    15-24     14951
4 1900    25-34     12161
5 1900    35-44      9273
6 1900    45-54      6437

> str(uspopage)
'data.frame':	824 obs. of  3 variables:
 $ Year     : int  1900 1900 1900 1900 1900 1900 1900 1900 1901 1901 ...
 $ AgeGroup : Factor w/ 8 levels "<5","5-14","15-24",..: 1 2 3 4 5 6 7 8 1 2 ...
 $ Thousands: int  9181 16966 14951 12161 9273 64
37 4026 3099 9336 17158 ...

積み上げ面グラフを選択して、
x軸にYearを、y軸にThousandsをマッピングし、AgeGroupごとにグループ化します。
f:id:MukkuJohn:20160911193054p:plain

他のグループ化したグラフと、変更できる書式は同じです。
f:id:MukkuJohn:20160911193155p:plain


100%積み上げ面グラフ

100%積み上げ棒グラフはあるのに、
なぜか、100%積み上げ面グラフはありません

そのため、事前にデータを加工する必要があります。
過去記事と同じく、Percent列を計算し、追加します。

> head(uspopage_prop)
  Year AgeGroup Thousands   Percent
1 1900       <5      9181 12.065340
2 1900     5-14     16966 22.296107
3 1900    15-24     14951 19.648067
4 1900    25-34     12161 15.981549
5 1900    35-44      9273 12.186243
6 1900    45-54      6437  8.459274

> str(uspopage_prop)
'data.frame':	824 obs. of  4 variables:
 $ Year     : int  1900 1900 1900 1900 1900 1900 1900 1900 1901 1901 ...
 $ AgeGroup : Factor w/ 8 levels "<5","5-14","15-24",..: 1 2 3 4 5 6 7 8 1 2 ...
 $ Thousands: int  9181 16966 14951 12161 9273 6437 4026 3099 9336 17158 ...
 $ Percent  : num  12.1 22.3 19.6 16 12.2 ...

y軸にPercentをマッピングして、その他は前のグラフと同じです。
f:id:MukkuJohn:20160911193600p:plain
グラフの種類を変えていないので、変更できる書式も変わりません。

折れ線の周りの網掛け

Power BI ではできません。



棒グラフと比較すると、折れ線グラフ関連は冷遇されているんですかね?
f:id:MukkuJohn:20160911195202p:plain

100%積み上げ棒グラフは、加工なしで作成できるので、
面グラフも加工なしで作成できるようになるといいですね。

次回は、Power BIで散布図を作ってみます。