クラスタ分析
クラスタリング 、クラスタ解析など呼ばれますが、データを一定のグループにまとめること。階層型と非階層型がある。
アンケート結果に対してクラスタ分析を行うことで、いくつかの傾向を読み取り、それに対してアクションを取ることを可能にしたい。
以下のサイトを参考にさせていただきました。
というか、ほぼコード流用です。
階層型クラスタリング
いくつくらいのグループに分けるのがいいのか、あらかじめ決まっていれば良いですが、ある程度、データからグループ数の参考を得たい。
その際は、樹形図(dendrogram デンドログラム)を使ってビジュアルに表現して、データの概要を把握する。
デンドログラムのコード
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt
import seaborn as sns#ウォード法を使用
questionnaire_s_hclust = linkage(questionnaire_s,metric="euclidean",method="ward")
plt.figure(figsize=(12,8))
dendrogram(questionnaire_s_hclust)
plt.savefig('figure_1.png')
plt.show()
4つのグループに分けると、3、6、3、8個に分類される、という参考になる。
非階層型クラスタリング
ある程度、クラスタ数が決まれば、k平均法による非階層型クラスターに分割して、分析をすることで、それぞれのクラスタの解釈をする。
k平均法のクラスタリングは、教師無し機械学習、と呼ばれます。
実際のコード
k平均法のおまじない
from sklearn.cluster import KMeans
#クラスタ数を4に設定
km = KMeans(n_clusters=4,random_state=42)
クラスタリングして、結果を保存
#numpyの行列に変換
questionnaire_arr = questionnaire_s.values
#kmeansを適用した結果のグルーピングの配列が出力として渡される
questionnaire_add_pred = km.fit_predict(questionnaire_arr)
#元のデータにクラスタIDを追加
questionnaire["cluster_ID"] = questionnaire_add_pred
クラスタIDをカテゴリに変更して、集計する。
#カテゴリカル変数に変更
questionnaire["cluster_ID"] = questionnaire["cluster_ID"] .astype("category")
questionnaire["cluster_ID"].value_counts()
実際の実行結果
8,5,4,3個の4つのグループが出来ました。階層型クラスタリングと結果は異なりますが、ある程度バランスが取れている、ことにしておきます。
更なる分析
4つのグループの特徴=回答の偏りがどのあたりにあるのか、を知るために、データを再構成していく。
以下により、ダミー変数を使って、クロス集計表のようなものを作成する。
#全ての項目をカテゴリ化
questionnaire = questionnaire[:].astype("category")#ダミー変数化したい列を指定するために列名を取得してリスト化、更にクラスタIDを除く
dummy_list = list(questionnaire.columns)[0:-1]#ダミー変数化したい列名を指定して全ての設問をダミー変数化
questionnaire_dmy = pd.get_dummies(questionnaire, columns=dummy_list)
次に、クラスタ毎で集計する。
クラスタIDでグループ化し数値を集約します
questionnaire_dmy_gp = questionnaire_dmy.groupby("cluster_ID")#グループ別に各設問の回答者数の合計を出します
questionnaire_dmy_gp_g = questionnaire_dmy_gp.sum().T
少し見やすくしてみる
questionnaire_dmy_gp_g.style.bar(color="#4285F4")
Q1に対して、クラスタIDが0、2,3のグループは、1-3で回答しているが、1のグループは4-5で回答している、という違いが見える。
クラスタマップの出力
plt.figure(figsize=(12,8))
sns.clustermap(questionnaire_dmy_gp_g,cmap="viridis")
plt.savefig('figure_2.png')
plt.show()
なんとなく、分かったような、分からないような。。。