毎回やる儀式

探索的データプロット

** データは図にする。プロットする。** これが分析の基本です。まずデータがどういう特徴を持っているかを,しっかりと目で把握しましょう。 それができていないと,データにモデルを当てはめるという話が始まりませんので。

ggplot2の導入

探索的データプロットのパッケージ,ggplot2をインストールします。

install.packages("ggplot2")

インストールしただけでは使えません。library関数(またはrequire関数)で装備します。

library(ggplot2)

まずはデータと全体設定を持ったggplotオブジェクトを作ります。

baseball <- read.csv("baseball2016.csv",na.strings="*")
gp <- ggplot(baseball,aes(x=year,y=pay,color=team))

点を打ってみましょう。

gp_point <- gp + geom_point()
plot(gp_point)

色だけじゃなく,大きさや形状を変えてプロットすることもできます。

gp <- ggplot(baseball,aes(x=year,y=pay,color=team,shape=position,size=height))
gp_point <- gp + geom_point()
plot(gp_point)

タイトルや軸ラベルも書いておきましょう。

gp <- ggplot(baseball,aes(x=year,y=pay,color=team,shape=position))
gp_point <- gp + geom_point()+xlab("プレイ期間")+ylab("年俸")+ggtitle("野球選手の年棒とプレイ期間の関係")
plot(gp_point)

画を複数に分けることもできます。

gp <- ggplot(baseball,aes(x=year,y=pay,color=team,shape=position))
gp_point <- gp + geom_point()+facet_wrap(~team)
plot(gp_point)

横軸がカテゴリカルであれば,箱ひげ図や棒グラフになります。

gp <- ggplot(baseball,aes(x=team,y=pay,fill=position))
gp_box <- gp + geom_boxplot()
plot(gp_box)

gp_bar <- gp + geom_bar(stat="identity",position="dodge")
plot(gp_bar)

# 平均が見たい
gp_bar <- gp + stat_summary(fun.y=mean,geom="bar",position="dodge")
plot(gp_bar)

# 中央値が見たい
gp_bar <- gp + stat_summary(fun.y=median,geom="bar",position="dodge")
plot(gp_bar)

エラーバーを追加する例。

gp <- ggplot(baseball,aes(x=position,y=pay,fill=position))
gp_bar <- gp + stat_summary(fun.y=mean,geom="bar",position="dodge") + 
                stat_summary(fun.data=mean_se,geom="errorbar",width=0.5)
plot(gp_bar)

様々な角度からデータをプロットし,分布の形状や変数間関係をしっかり見極める癖をつけましょう。

本日の課題1

  • 年俸と守備位置とBMIの関係をグラフにして表現してください。何グラフを用いても良い。

Clustering

次はクラスタリングです。クラスタリングとは 似ているもの同士をまとめる という操作です。例えば野球データでは,143人分のデータがあります。143人にはそれぞれの人生があるでしょうが,一人一人見ていくわけにもいかない場合,似ているいくつかのグループ(クラスター)にわけて考えた方が効率的です。

ということで,分類法は色々あるのですが,今日は一番簡単な「階層的クラスタリング」という話をしたいと思います。

階層的クラスタリング

階層的クラスタリングとは,「似ている」ケースをまとめていって,まとまったものをさらにまとめて,さらにそれをまとめて・・・と繰り返していく方法です。上に上に,ヒエラルキー(階層)を登るように積み上げていくので,階層的クラスタリングといいます。

ちなみに,非階層的クラスタリングとは,最初からいくつにまとめるかを決めてまとめ上げていく方法です。

似ている,とは。

データで考えて見ましょう。まずはわかりやすく,身長と体重という部分的なデータだけで考えて見ます。

# サブセットphysicalを作ります
physical <- subset(baseball,select=c("height","weight"))
# 一人目
physical[1,]
##   height weight
## 1    186     98
# 二人目
physical[2,]
##   height weight
## 2    180     93

この二人はどれぐらい似ているでしょうか?似ている=数字が近い,と言う意味で考えると,引き算をすればいいでしょう。

physical[1,]-physical[2,]
##   height weight
## 1      6      5

これを足し合わせて二人の距離とします。引き算のまま,ただ足すのではなく,三平方の定理を使って, \[ d_{12} = \sqrt{(x_1-x_2)^2+(y_1-y_2)^2} \] とすることで符号に関わらず二人の距離を測ることができます。

sqrt((physical[1,1]-physical[2,1])^2+(physical[1,2]-physical[2,2])^2)
## [1] 7.81025

これが二人の距離です。 これを全員の組み合わせ分をやると大変!ですが,Rは関数一気にやってくれます。

# 1人目から5人目まで,全ての組み合わせの距離
dist(physical[1:5,],method="euclidean")
##           1         2         3         4
## 2  7.810250                              
## 3 26.000000 33.120990                    
## 4 13.601471  6.324555 39.357337          
## 5 13.453624 21.260292 15.000000 26.907248

全員分を計算すると(143*143-143)/2の数字がでます。全部印字すると大変なので,オブジェクトの中に入れておきます。

dist.physics <- dist(physical,method="euclidean")

クラスタリングの方法

この距離データを使って似ている人は同じグループとする,というのを反復して行きます。関数はhclustです。

クラスターを積み重ねていくときはいくつかの方法があるのですが,「結構綺麗に分かれてわかりやすい」ことで有名なのがWard法です。この方法で分類した例を示します。

result <- hclust(dist.physics,method="ward.D2")
plot(result)

こうして枝葉がどんどん積み上がりました。これの頃合いを見て,枝を切ります。例えば2グループに分けたいとしましょう。関数はcutree です。

cutree(result,2)
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18 
##   1   1   1   2   1   1   1   1   1   1   1   1   1   1   1   1   1   1 
##  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36 
##   2   2   2   2   2   2   2   2   1   2   2   2   2   2   2   2   2   2 
##  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54 
##   2   2   2   2   1   2   2   2   2   2   2   2   2   1   2   2   1   2 
##  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72 
##   2   2   1   2   1   2   1   2   2   2   2   2   2   2   2   2   1   2 
##  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90 
##   1   1   1   2   2   2   1   2   2   2   1   2   1   1   1   1   1   2 
##  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 
##   1   1   1   1   1   1   1   1   1   1   2   2   1   1   2   2   2   1 
## 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 
##   2   1   2   2   2   2   2   2   2   1   2   2   2   2   2   2   2   2 
## 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 
##   1   2   2   2   2   2   1   1   2   2   2   2   2   2   2   2   1

こうすることで,143人が2つのグループに分かれました! この分類法をデータに追加しておくと便利です。

baseball$class <- cutree(result,2)
baseball$class <- factor(baseball$class,labels=c("CL1","CL2"))

どういうグループなんだろうね?

今回は,なんだかわからないけど似ているもの同士分類したわけですが,どう言う分かれ方をしたか気になりますよね。 ということで,データは図にしろという原理に戻って見たいと思います。

library(ggplot2)
g <- ggplot(baseball,aes(x=height,y=weight,color=class))
g <- g + geom_point()
plot(g)

そうだね!体のゴツさだね!

でもこれでは面白くないです。身長と体重を元に分類したら,身長と体重を元に分類できた,という話だからです。クラスターの説明は,クラスターを作った変数以外の変数でした方が面白いでしょう。たとえば,収入 とかね。

g <- ggplot(baseball,aes(x=class,y=pay,color=class))
g <- g + geom_boxplot()
plot(g)

体が小さい人の方が平均年収が低いようだ,ということがデータから示されました。

このように,クラスタリングは「どのような分類になったか」というのを後で考えないといけません。その時に,探索的データプロットの力を借りるといいでしょう。

本日の課題2

  • 身長・体重以外の任意のデータを使って階層的クラスタリング(ユークリッド距離,Ward法)を行い,プロットを見て複数のクラスに分割してください。
  • その分類データを使って,探索的データプロットをおこなってください。

発展課題(加点対象)

  • 分類データを独立変数とし,統計的にデータの特徴を論じなさい。頻度主義的アプローチでもベイジアンアプローチでもよい。