購買データを使って顧客のクラスター分析を行ってみた

# 概要
購買データをもとに顧客のクラスター分析を行いました。クラスター分析を行った後、各々のセグメントがどういった特徴を持つのかを可視化しました。

# はじめに
機械学習を行う際には、多くの場面でデータ分析が必要となってきます。持っているデータをどんな切り口で見ていくか、またどんなふうに加工を施すか。
そういった引き出しを増やしていきたいところですが、Pythonを使ってのデータ分析教材はあまり多くないのが現状です。(アヤメやタイタニックの話は飽きたよぉ…)
そこで「Pthonじゃなくても、データ分析の手法を学べる教材を買って、それを自分なりにPythonで再現すれば引き出しを増やせるんじゃない？」と考えました。
今回手にした本は下記となります。

#### [**Rビジネス統計分析 [ビジテク]**](https://www.amazon.co.jp/R%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E7%B5%B1%E8%A8%88%E5%88%86%E6%9E%90-%E3%83%93%E3%82%B8%E3%83%86%E3%82%AF-%E8%B1%8A%E6%BE%A4-%E6%A0%84%E6%B2%BB/dp/4798149500/ref=sr_1_1?adgrpid=50883860102&gclid=CjwKCAiAmNbwBRBOEiwAqcwwpa7BggXF27rE-sYlO1xvJXmMQn-PeUq6EHGRIMkxBD-lQKWtl7MmsRoC888QAvD_BwE&hvadid=338575431599&hvdev=c&hvlocphy=1009433&hvnetw=g&hvpos=1t2&hvqmt=e&hvrand=7508171191131142832&hvtargid=aud-759377471893%3Akwd-411533392957&hydadcr=13897_10891658&jp-ad-ap=0&keywords=r%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E7%B5%B1%E8%A8%88%E5%88%86%E6%9E%90&qid=1578535237&sr=8-1)

>【本書の目的】
本書は、ビジネスの現場に蓄積する大量のデータから、Rを用いて
自社の売り上げに直結するビックXを求めるビジネス統計分析手法を
まとめた書籍です。概論と実際の分析手法をセットにして、わかりやすく
解説しています。

# 使用データ
上記、書籍のファイルを使用させていただきました。

　・購買履歴情報 [buying.csv]

# 実際のコード

### 1.データの読み込み

```python
# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib
%matplotlib inline
```


```python
# ファイルの読み込み・表示
buying = pd.read_csv("buying.csv",encoding='cp932')
buying.head()
```

![Data1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/0ef202dc-2d8b-e68e-118b-650cead5f885.jpeg)


### 2.クロス集計を行う

```python
# クロス集計による併売データを作成する
buying_mat = pd.crosstab(buying['id'], buying['category'])
buying_mat.head()
```

![Data2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/c2b44e68-f813-85d1-6ec6-693b62f0f4b8.jpeg)


### 3.ダミー変数化したうえで階層クラスター分析

```python
# 併売データをダミー変数化する
# １回以上購入していれば「１」、それ以外なら「0」とする
buying_mat1 = buying_mat.copy()
for i in range(len(buying_mat1)):
    for j in range(len(buying_mat1.columns)):
        if buying_mat1.iloc[i, j] > 1:
            buying_mat1.iloc[i, j] = 1

buying_mat1.head()
```

![Data3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/71980632-97f9-0600-56af-c871617b6b1a.jpeg)

```python
# クラスター分析のライブラリのインポート
from scipy.cluster.hierarchy import dendrogram, linkage
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
```

```python
# 階層型クラスタリングの実施
# ウォード法 x ユークリッド距離
linkage_result = linkage(buying_mat1, method='ward', metric='euclidean')
```

```python
# クラスター分けするしきい値を決める
threshold = 0.7 * np.max(linkage_result[:, 2])
```

```python
# 階層型クラスタリングの可視化
plt.figure(num=None, figsize=(16, 9), dpi=200, facecolor='w', edgecolor='k')
dendrogram(linkage_result, labels=buying_mat1.index, color_threshold=threshold)
plt.axhline(7, linestyle='--', color='r')
plt.show()
```
![graph1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/d3199853-aa16-52f4-88eb-bdcb4bdc6833.png)

```python
# クラスタリング結果の値を取得
clustered = fcluster(linkage_result, threshold, criterion='distance')
```

```python
# クラスタリング結果を確認
print(clustered)
```

![Data4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/9ae22510-854f-d215-2415-63a10f0132b3.jpeg)

### 4.ダミー変数化しない場合の階層クラスター分析

```python
# 階層型クラスタリングの実施
# ウォード法 x ユークリッド距離
linkage_result2 = linkage(buying_mat, method='ward', metric='euclidean')
```

```python
# クラスター分けするしきい値を決める
threshold2 = 0.7 * np.max(linkage_result2[:, 2])
```

```python
# 階層型クラスタリングの可視化
plt.figure(num=None, figsize=(16, 9), dpi=200, facecolor='w', edgecolor='k')
dendrogram(linkage_result2, labels=buying_mat.index, color_threshold=threshold2)
plt.axhline(23, linestyle='--', color='r')
plt.show()
```
![graph2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/ac5dbe5b-6f3a-3297-c08e-bb32e5c70d0d.png)


### 5.階層クラスター分析の結果を元データと結合する

```python
# 階層クラスター分析の結果をDataFrame化
_class = pd.DataFrame({'class':clustered}, index= buying_mat1.index)
_class.head()
```

![Data5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/b9b7ab40-3a51-6862-4085-4ee7438a3817.jpeg)

```python
# 元データと分析結果を結合
buying_mat2 = pd.concat([buying_mat1, _class] ,axis=1)
buying_mat2.head()
```
![Data6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/eca033ec-9dec-0c90-a102-8e3151aa0342.jpeg)

```python
# 各セグメントの顧客数を確認 
buying_mat2.groupby('class').size()
```

![Data7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/6a4ef1d4-9528-4620-e5cc-f912c4f2a686.jpeg)

### 6.各セグメントにおける併売傾向の特徴をつかむ

```python
# セグメントごとにすべての商品カテゴリの平均値を算出
cluster_stats = np.round(buying_mat2.groupby('class', as_index=False).mean() ,2)
cluster_stats.head()
```

![Data8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/ee2711e2-79ad-f4bd-a972-29ccc8eadbe8.jpeg)

```python
# グラフ描画のために、縦長のデータ形式に変換
mat_melt = pd.melt(cluster_stats, id_vars='class', var_name='Category',value_name='Rate')
mat_melt.head()
```

![Data9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/39927ea2-6ad5-0167-9f9e-36921c46b36e.jpeg)

```python
# セグメントの特徴をグラフにする
fig = plt.figure(figsize =(20,8))
ax1 = fig.add_subplot(1, 5, 1)
sns.barplot(x='Category', y='Rate', data=mat_melt[mat_melt['class'] == 1], ax=ax1)
plt.xticks(rotation=90)
plt.ylim(0, 1)

ax2 = fig.add_subplot(1, 5, 2)
sns.barplot(x='Category', y='Rate', data=mat_melt[mat_melt['class'] == 2], ax=ax2)
plt.xticks(rotation=90)
plt.ylim(0, 1)

ax3 = fig.add_subplot(1, 5, 3)
sns.barplot(x='Category', y='Rate', data=mat_melt[mat_melt['class'] == 3], ax=ax3)
plt.xticks(rotation=90)
plt.ylim(0, 1)

ax4 = fig.add_subplot(1, 5, 4)
sns.barplot(x='Category', y='Rate', data=mat_melt[mat_melt['class'] == 4], ax=ax4)
plt.xticks(rotation=90)
plt.ylim(0, 1)           
    
ax5 = fig.add_subplot(1, 5, 5)
sns.barplot(x='Category', y='Rate', data=mat_melt[mat_melt['class'] == 5], ax=ax5)
plt.xticks(rotation=90)
```

![graph4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/844507ed-53c7-73b6-eafe-2eb112e8ec0a.png)

```python
# セグメントの特徴をグラフにする(for文でグラフ描画)
groups = mat_melt.groupby('class')
fig = plt.figure(figsize =(20,8))

for name, group in groups:
    _ax = fig.add_subplot(1, 5, int(name))
    sns.barplot(x='Category', y='Rate', data=group , ax=_ax)
    plt.title('Class' + str(name))
    plt.xticks(rotation=90)
    plt.ylim(0, 1)
```

![graph4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555643/844507ed-53c7-73b6-eafe-2eb112e8ec0a.png)

各セグメントの特徴から購入層を推定してみる。
・Class1
　・雑貨の購入率が高い
　　⇒雑貨好きの層？
・Class2
　・男性物を除いた項目の購入率がまんべんなく高い
　　⇒子供のいる家庭・女性客？
・Class3
　・ベビー用品、マタニティ、男性物と購入率が高い
　　⇒子供のいる家庭・男性客？
・Class4
　・女性物の購入率が高い
　　⇒女性客？
・Class5
　・女性物の購入率が高い、ただしClass4とは購買傾向が異なる
　　⇒女性客(Class4とは購買傾向が異なる)？