** データは図にする。プロットする。** これが分析の基本です。まずデータがどういう特徴を持っているかを,しっかりと目で把握しましょう。 それができていないと,データにモデルを当てはめるという話が始まりませんので。
探索的データプロットのパッケージ,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)
様々な角度からデータをプロットし,分布の形状や変数間関係をしっかり見極める癖をつけましょう。
次はクラスタリングです。クラスタリングとは 似ているもの同士をまとめる という操作です。例えば野球データでは,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)
体が小さい人の方が平均年収が低いようだ,ということがデータから示されました。
このように,クラスタリングは「どのような分類になったか」というのを後で考えないといけません。その時に,探索的データプロットの力を借りるといいでしょう。