Rによるデータ分析

Rによるクラスター分析

クラスター分析 は、 データマイニング の手法として、よく知られています。 ここでは、その使い方の紹介になります。

基本的な分析

Rを使ったクラスター分析の実施例になります。 クラスター分析の手法は、いろいろありますが、共通部分は一緒に書いています。

下記は、コピーペーストで、そのまま使えます。 下記のコードを使った場合、X-means以外は、このページの一番上にある色分けのグラフと同じ結果になります。 この例では、入力データは量的データになっていることを想定しています。 質的データがあるとエラーになります。

共通部分(入力データ)

以下に、複数の方法がありますが、入力データの作り方は同じなので、ここにまとめています。

この例では、Cドライブの「Rtest」というフォルダに、 「Data1.csv」という名前でデータが入っている事を想定しています。

入力データの読み込みをします。 Data10からData11への変換は、すべての列を0と1の間のデータにするためのものです。 DBSCANをする時はあった方が良いですし、どの手法だとしても、身長と体重など、単位が違う変数が混ざっている場合は必須です。
setwd("C:/Rtest") # 作業用ディレクトリを変更
Data1 <- read.csv("Data1.csv", header=T)
# データを読み込み
Data10 <- Data1[,1:2]#
# クラスター分析に使うデータを指定。ここでは1〜2列目の場合
Data11 <- Data10
# 出力先の行列を作る

#以下の3行は、前処理としてデータを正規化する場合は必要
for (i in 1:ncol(Data10)) { # ループの始まり。データの列数を数えて同じ回数繰り返す
Data11[,i] <- (Data10[,i] - min(Data10[,i]))/(max(Data10[,i]) - min(Data10[,i]))
}
# ループの終わり

#以下の2行は、前処理としてデータを主成分にする場合は必要
pc <- prcomp(Data11, scale=TRUE,tol=0.01) # 主成分分析
Dat11 <- as.data.frame(pc$x)
# 寄与率の高い主成分を抽出

階層型

階層型はいろいろありますが、非階層型のk-means法や混合分布法と近い結果になる方法で一番使いやすいのがウォード法で、 DBSCANと近い結果になるのが最近接法なので、下記はその2つを例にしています。

library(plotly)
library(ggdendro)
Data11_dist <- dist(Data11)
# サンプル間の距離を計算
hc <- hclust(Data11_dist, "ward.D2")
# ウォード法による階層型クラスター分析
#plot(hc)
# 一般的なデンドログラム
ggplotly(ggdendrogram(hc, segments = TRUE, labels = TRUE, leaf_labels = TRUE, rotate = FALSE, theme_dendro = TRUE))
# 拡大可能なデンドログラム
k-means
デンドログラムから、狙い通りに3つのグループに大きく分かれている様子がわかります。

最近接法では、「single」にします。
hc <- hclust(Data11_dist, "single") # 最近接法による階層型クラスター分析

この例は、データが60個なのでできなくもないのですが、サンプルが多い時は、 デンドログラムから各サンプルがどのように分かれるのかを読み取れなくなります。 結果をデータとして出力する方法ですが、 各サンプルを3つのグループに分けると、どのグループに所属するのかは、下記のようにすると出力できます。
output <- cutree(hc,k=3)# 3個にグループ分け

非階層型(k-means法)

km <- kmeans(Data11,3) # k-means法で分類。これは3個のグループ分けの場合
output <- km$cluster
# 分類結果の抽出

非階層型(X-means法)

X-means法の使い方は、k-means法と似ていますが、ライブラリのインストールが事前に必要です。 また、細かいところが少し違います。

library(clusternor) # ライブラリを読み込み
Data11 <- as.matrix(Data11)
# データを行列に変換
xm <- Xmeans(Data11,10)
# X-means法で分類。最大のグループ数を10個に指定。
output <- xm$cluster
# 分類結果の抽出

非階層型(混合分布法)

混合分布でも、ライブラリのインストールが事前に必要です。

library(mclust) # ライブラリを読み込み
mc <- Mclust(Data11,3)
# 混合分布で分類。これは3個のグループ分けの場合
output <- mc$classification
# 分類結果の抽出

混合分布の場合は、データの分類だけではなく、他のデータがあった時に、分類に使ったデータからわかった分類のどれに該当するのかの予測ができます。 これは、 予測のためのソフトの使い方 と同じです。
Data2 <- read.csv("Data2.csv", header=T) # テストデータを読み込み
for (i in 1:ncol(Data2)) {
# ループの始まり。データの列数を数えて同じ回数繰り返す
Data21[,i] <- (Data2[,i] - min(Data2[,i]))/(max(Data2[,i]) - min(Data2[,i]))
}
# ループの終わり
output2 <- predict(mc, Data21)
# テストデータの分類を作成

ファイルに出力した内容の例が下の表になります。 最終的に、3つのグループのどれになるのかを予測しただけではなく、それぞれのグループに属する確率がわかるようになっています。
k-means

非階層型(DBSCAN)

DBSCANでも、ライブラリのインストールが事前に必要です。 DBSCANは、epsの設定が悩みどころになりますが、前処理で正規化していれば、データの範囲は最大で1なので、 グループの範囲の目安は、0.1から0.3くらいで良いはずです。

library(dbscan) # ライブラリを読み込み
dbs <- dbscan(Data11, eps = 0.2)
# DBSCANで分類。epsは、コア点からの距離の範囲です。ここでは、0.2にしました。
output <- dbs$cluster
# 分類結果の抽出

階層型(HDBSCAN)

HDBSCANでは、epsの設定はしなくても良いのですが、minPtsを設定しないとエラーになります。 minPtsは、核になるクラスタを構成するサンプルの数で、これが小さいと、細かいクラスタができやすくなります。

library(dbscan) # ライブラリを読み込み
dbs <- hdbscan(Data11, minPts = 5)
# HDBSCANで分類。minPtsは、グループのサンプル数の最小値。
output <- dbs$cluster
# 分類結果の抽出

共通部分(出力)

Rには、クラスター分析用のグラフのパッケージもありますが、ここでは汎用的な ggplot2 を使う例になります。

library(ggplot2) # パッケージの読み込み
Data <- cbind(Data1, output)  # 最初のデータセットにグループ分けの結果を付ける
Data$output <-factor(Data$output) # グループの変数を文字列型にする
Data$Index <-row.names(Data) # Indexという名前の列を作り、中身は行番号にする
ggplot(Data, aes(x=X1, y=X2)) + geom_point(aes(colour=output))
# 二次元散布図 色分け・形分け

ここで、下のデータのようにデータが少ない場合は、行番号をプロットする方法も便利です。
k-means
ggplot(Data, aes(x=X1, y=X2,label=Index)) + geom_text(aes(colour=output))# 言葉の散布図
k-means

各サンプルの名前の列がある場合は、それを使うこともできます。
ggplot(Data, aes(x=X1, y=X2,label=Name)) + geom_text(aes(colour=output))# 言葉の散布図
k-means

write.csv(Data, file = "Output.csv") # データをcsvファイルに出力

決定木によるクラスタリングの分析

決定木によるクラスタリングの分析 です。 クラスター分析のクラスターがなぜ、そのようになったのかは、クラスター分析からはわからないため、 決定木 を使って調べます。

この例では、Cドライブの「Rtest」というフォルダに、 「Data1.csv」という名前でデータが入っている事を想定しています。 ここで使っているデータは、3次元空間に6個のグループがある場合です。
Decision Tree

# まず、入力データを用意します。
setwd("C:/Rtest") # 作業用ディレクトリを変更
Data10 <- read.csv("Data1.csv", header=T)
# データを読み込み
Data11 <- (Data10 - apply(Data10,2,min))/(apply(Data10,2,max)-apply(Data10,2,min))
# すべての変数のデータを、0から1の間のデータにする。

# クラスター分析をします。
library(dbscan) # ライブラリを読み込み
dbs <- dbscan(Data11, eps = 0.2)
# DBSCANで分類。epsは、コア点からの距離の範囲です。ここでは、0.2にしました。
output <- dbs$cluster
# 分類結果の抽出
Data <- cbind(Data10, output)  # 最初のデータセットにグループ分けの結果を付ける
Data$output <-factor(Data$output) # グループの変数を文字列型にする

# 決定木をrpartにする場合です。
library(partykit) # ライブラリを読み込み
library(rpart)
# ライブラリを読み込み
treeModel <- rpart(output ~ ., data = Data)
# rpartを実行
plot(as.party(treeModel))
# グラフにする。
Decision Tree

# 決定木をCHAIDにする場合です。 量的データを質的データにする手間があります。 この例では、その手間の効果がわかりませんが、 N進木 になるので、データの構造が複雑な時に理由の考察がしやすくなります。
library(CHAID) # ライブラリを読み込み
Data <- read.csv("Data.csv", header=T, stringsAsFactors=TRUE)
# データを読み込み
Data$X1 <- droplevels(cut(Data$X1, breaks = 5,include.lowest = TRUE))
# 5分割する場合。元のデータに質的データを追加する。
Data$X2 <- droplevels(cut(Data$X2, breaks = 5,include.lowest = TRUE))
# 5分割する場合。元のデータに質的データを追加する。
Data$X3 <- droplevels(cut(Data$X1, breaks = 5,include.lowest = TRUE))
# 5分割する場合。元のデータに質的データを追加する。
treeModel <- chaid(Y ~ ., data = Data)
# CHAIDを実行
plot(treeModel)
# グラフにする。
Decision Tree





Tweet データサイエンス教室