MBA名授業:Rを使いこなす基礎練習(クラスター分析)

目次

はじめに

経営大学院(MBA)の授業は面白かった。豊田教授の授業は以前投稿したが、今回はクラスター分析についてまとめた。データ分析の基本は分類、関係、縮約、要約の4つだ。このうちの分類はいわゆる似た者集めだ。しかし、注意すべきはこの分類結果は、分類の仕方によって異なる。手法によっても異なるし、何個に分類するかによって答えは全く異なる。その意味では、分類は仮説であるとされている。大切なことは分類結果を前提として分析を行い、妥当性を検証することだ。また、分類の仕方では、最近のITの進化に伴って教師なし分類手法が進化してきた。これは人工知能における機械学習や深層学習の成果による部分がありそうだ。

クラスター分析(階層型)

一見バラバラに見えるデータをまとめていくアルゴリズムは複数ある。もっとも直感的に理解しやすいのは、データとデータの距離が違いものをまとめていく最短距離法だろう。例えば、下の図のようなデータで、AとBが近く、CとDが近い。Eは少し離れているというものを階層クラスターで描いたものをデンドログラムという。個人的にはデンドログラムという響きや恣意的な要素なく、教師なしで自動分類してくれるこの考え方は好きだ。
f:id:hiroshi-kizaki:20191106182614j:plain
出典:クラスター分析の手法②(階層クラスター分析) | データ分析基礎知識

デンドログラム(Dendrogram)

日本語で言えば樹形図だ。デンドログラムは木を意味する古代ギリシャ語のデンドロン(δένδρον)と数学的な図形を意味するグラマンマ(γράμμα)の造語だ。ちなみに、英語のtopをギリシャ語で翻訳するとブロウザ(μπλουζα)だった。ということは、Tree Topはデンドロブロウザか(笑)。LuckyOceanもギリシャ語にするとティケロス・オケアノス(Τυχερός ωκεανός)だった。
f:id:hiroshi-kizaki:20191106184536p:plain
出典:http://www.ivis.co.jp/text/20180411.pdf

クラスター分析(kmeans)

デンドログラムは、樹形図として見える化してくれるので、わかりやすい。因子数も任意に決めることができる。しかし、欠点はその処理が複雑なことだ。データ数が少ないうちは良いけど、ビッグデータになると指数関数的に処理時間が長くなり、実用的とは言えなくなる。そのため、データ量が多くても、効率的にグループ分けしてくれる方法がk-means法によるクラスター分析だ。これは、次の手順でクラスタリングを行う。1)まず任意の数の初期値を設定する。2)その初期値との距離でサンプルデータをグループ化する。3)グループかされたデータの重心の位置を計算する。4)新しい重心に基づいて2)の処理を行う。5)新たにグループかされたデータの重心を再計算する。この4)と5)は基本的に2)と3)と同義であるため、これを何回繰り返すかでデータが決まる。時系列分析する場合には、あえて繰り返し数を1回にしたり、初期値を固定した離する。詳しくは出典で引用したYouTubeの画像がわかりやすいかもしれない。
f:id:hiroshi-kizaki:20191106185041p:plain
出典:www.youtube.com

ファジーc-means法

クラスター分析を行う場合に、それぞれのデータは必ずどれが一つのグループに属しているという前提に立つのが従来の考え方だ。しかし、ファジーc-means法では、確率論的にグループAに属する確率PAとグループBに属する確率PBという前提があってもいいんじゃないという考え方だ。数式は少し難解に見えるかもしれないが、選択できないことだってあるよねというゆるい考え方は好きだ。
f:id:hiroshi-kizaki:20191106190637p:plain
f:id:hiroshi-kizaki:20191106190647p:plain
出典:Fuzzy c-means clustering algorithm – Data Clustering Algorithms

参考

Rの復習(ケース1)

(1) データの読み取る。

brand<- read.csv(“brand.csv“,row.names = 1)
#brandという名前のCSVデータを読み取る。

(2) 先頭6行を表示する。

head(brand)
# headで先頭6行を表示し、データが正しいことを確認

(3) サブセットを作成する。

brand.data1<- brand[,c(1,2)] # Case1 二つのブランド(Brand1,2)で階層クラスター分析を行う
# サブセットの作成
# 階層クラスター分析では、距離を計算するために、分類に用いるデータのみを
# サブセット(部分データ)として作成する。
# brand[,c(1,2)]はbrandからすべての行と、1,2列を抜き出すというコマンド
# [行,列]で、何も入れないと“すべて”、数字を入れると“その数字の行または列”を抽出
# 数字の指定は、c( )の括弧の中に、カンマ区切りで入れるのが基本

(4) 先頭6行を表示する。

head(brand.data1)
#headで先頭6行を表示し、データが正しいことを確認

(5) 散布図にプロットして、ラベルを描く。

plot(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20))
text(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20),
labels=rownames(brand.data1))
# ラベル付き散布図で全体傾向を確認する
# plotは(量的変数,量的変数)で散布図を描く。xlimは横軸の範囲、ylimは縦軸の範囲を指定
# textは散布図の点の代わりにラベルを描く。labelsで指定する。

(6) プロットを小さくする。

plot(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20), cex=0.5)
text(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20),
labels=rownames(brand.data1))
# plotの点を小さくするには、cexで点の大きさを指定する。

(7) プロットを非表示にして、ラベルのみ表示とする。

plot(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20), type = “n”)
text(brand.data1$Brand1,brand.data1$Brand2,xlim=c(0, 20),ylim=c(0, 20),
labels=rownames(brand.data1))
# plotの点をなし(表示させない)には、type = “n”とする。

(8) dist関数で距離を計算する。

brand.data1.d<-dist(brand.data1)
brand.data1.d
# 似たもの集めをするために対象間(20人)の距離を求める
# dist関数によって行列の形で距離が求まる

(9) ウォード法で計算する。

hc1<-hclust(brand.data1.d,method=”ward.D2″)
# 階層型クラスター分析をウォード法にておこない、デンドログラムを出力する
# hclust関数で計算する
# メソッドはウォード法とするが、ward.D2になることに注意
# ward.Dはバグがあるので使わない(古いテキストなどはward.Dになっている)

(10) デンドログラムを表示する。

plot(hc1,hang=-1,main=”ウォード法”)
# デンドログラムを出力する
# mainは図のタイトル、hangはデンドログラム下部の揃わせ方に関連

Rの復習(ケース2)

Case2 議論:3つのブランドでクラスター分析を行い2つの場合と比較する

(1) 所属グループの変数を作る。

brand.data2<- brand[,c(1,2,3)] # デンドログラムを元にクラスター数を決定し、所属グループという変数を作る
# Brand1から3のデータを抽出し、保存
# brand[,c(1,2,3)]はbrandからすべての行と1,2,3列を抜き出すというコマンド

(2) データを表示する。

head(brand.data2)
# headで先頭6行を表示し、データが正しいことを確認

(3) dist関数で距離を計算する。

brand.data2.d<-dist(brand.data2)
# 似たもの集めをするために距離を求める:dist関数

(4) ウォード法でデンドログラムを出力する。

hc2<-hclust(brand.data2.d,method=”ward.D2″)
plot(hc2,hang=-1,main=”ウォード法:Brand1&2&3″)
# 階層型クラスター分析をウォード法にておこない、デンドログラムを出力する

Rの復習(所属セグメントの特定)

(1) 幾つで区切るかを指定する。

plot(hc2,hang=-1,main=”ウォード法:Brand1&2&3″)
rect.hclust(hc2, k = 4)
#所属セグメントの特定

(2) プロットする。

plot(hc2,hang=-1,main=”ウォード法:Brand1&2&3″)
rect.hclust(hc2, k = 3)
#デンドログラムを見ていくつに区切るかを決めたら、その所属セグメントを求める
#いくつに区切るか(k=で指定)を見やすくするためにrect.hclustを使うと便利
#ここではk=4として、4つに区切る。

(3) 標準出力位置に戻す。

par(mfrow=c(1,1))
# 標準出力の1行1列に戻しておく

(4) cutreeを用いる。

cutree(hc2,k=4)
# cutreeを用いて、所属セグメントを求める
# 今回は4セグメントとして分析してみる

(5) as.factorとして保存する。

group_3br_4seg<-as.factor(cutree(hc2,k=4))
# 保存する際に、数値で保存すると質的変数にならないので
# as.factorを使って(factor:因子・選択肢)として保存する。

(6) 4つのグループに再編する。

group_3br_4seg
# 中身を見ると、Levelsがあることが分かる

(7) 列を統合する。

brand<-cbind(brand,group_3br_4seg)
# 元のデータにこの所属セグメントを追加する
# cbindとは、column(列)方向のデータのバインド(統合)するためのコマンド
# こうすることで、元の「brand」というデータの一番右に「group」という列が追加される

(8) 先頭6行を表示する。

head(brand)
# headで先頭6行を表示し、データに所属セグメントが追加されていることを確認

(9) 分類したグループの特徴を確認する。

ave.table_3br_4seg<-cbind(
tapply(brand$Brand1,brand$group_3br_4seg,mean),
tapply(brand$Brand2,brand$group_3br_4seg,mean),
tapply(brand$Brand3,brand$group_3br_4seg,mean)
)

ave.table_3br_4seg
# 分類したグループの特徴を確認する
# tapplyとは、ある変数を、何かの基準で集計するときに使うコマンド
# tapply(集計したい変数,集計基準,集計方法)

(10) 行と列に名前をつける。

colnames(ave.table_3br_4seg)<-c(“Brand1″,”Brand2″,”Brand3”)
rownames(ave.table_3br_4seg)<-c(“Segment1″,”Segment2″,”Segment3″,”Segment4”)
# colname、rownameはデータの行と列に名前をつけるコマンド

(11) 表示を小数点以下2桁で丸める。

round(ave.table_3br_4seg,2)
# roundは、小数点以下を四捨五入するコマンド

(12) レーダーチャートを描く。

library(plotrix)
radial.plot(ave.table_3br_4seg, rp.type =”p”, labels = colnames(ave.table_3br_4seg),
lty = 1:3, lwd = 3)
legend(“topright”, legend = rownames(ave.table_3br_4seg), col = 1 : 3, lty = 1:3 )
# レーダーチャートを描いて傾向を把握する
# plotrixライブラリーを用いると便利
# 以下、installは、頭の#を外して一回だけ行う
# install.packages(“plotrix”)

(13) 分類したグループを棒グラフで表示する。

par(mfrow=c(1,2))
plot(brand$sex,brand$group_3br_4seg, main=”性別と所属セグメント”)
plot(brand$age,brand$group_3br_4seg, main=”年代2択と所属セグメント”)
# 分類したグループをy(結果系)として分析する
# 100%積み上げ棒グラフで確認する
# par(mfrow=c(1,2))の場合、1行2列で出力

(14) クロス集計する。

table1<-table(brand$sex,brand$group_3br_4seg)
table2<-table(brand$age,brand$group_3br_4seg)
# クロス集計表で確認する

(15) 結果を表示する。

table1
table2

以上

最新情報をチェックしよう!