階層クラスター分析（ウォード法）による顧客セグメンテーション

階層クラスター分析（ウォード法）による顧客セグメンテーションを行ったので紹介します。


<h2>前置き</h2>

私はとある採用選考手法のツールを開発しているスタートアップ企業に所属しています。
今までは社長の紹介経由で数十社にツール導入してもらいましたが、今後はより多くの企業にアプローチしていきたいと計画しています。

とはいえ闇雲に営業活動を行っても無駄打ちが多くなる恐れがあるため、<strong>既存顧客や競合他社の顧客データをもとに「どういった属性の企業であればこの採用選考手法を導入しているのか？」を明らかにしたい</strong>と考えました。

以上の経緯から今回「階層クラスター分析（ウォード法）による顧客セグメンテーション」を行ってみました。

>実行環境：「Google Collaboratory」


<h2>分析の流れ</h2>


<h3>①データ収集</h3>
今回データを収集・分析する企業は以下です。

<ul>
<li>自社の顧客</li>
<li>競合ツールのサイトにて、企業ロゴや導入インタビュー記事が載っている企業</li>
<li>求人サイトにて、募集要項の選考ステップに対象の採用選考手法を入れている企業</li>
</ul>
<br>

これらで177企業をリストアップし、会社HP/求人サイトから以下8つの特徴データを収集しました。

<ol>
<li>業種　　　　　　：整数型（業種分類コード）</li>
<li>創業年数　　　　：整数型</li>
<li>外資／内資　　　：論理型</li>
<li>上場／非上場　　：論理型</li>
<li>資本金（万円）　：整数型</li>
<li>従業員数　　　　：整数型</li>
<li>平均年齢　　　　：浮動小数点型（小数点1桁まで）</li>
<li>都道府県　　　　：整数型（都道府県コード）</li>
</ol>
<br>

以下の表がその結果になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/6e88688c-288e-2c0a-7310-9d8b0003f7d7.png)


<h3>②データクレンジング</h3>
収集できなかった特徴量も多かったので、以下手法でデータクレンジングを実施しました。

```python:cleansing.py
# 列「平均年齢（average_employee_age）」の欠損値を平均値代入法で補完
clients['average_employee_age'] = clients['average_employee_age'].fillna(clients['average_employee_age'].mean())

# 他列の欠損値は行ごと削除
dropped_clients = clients.dropna()

```

これによって対象企業数は177企業から154企業に。
また「創業年数」「資本金（万円）」「従業員数」「平均年齢」について標準化を行いました。

```python:scaler.py
from sklearn.preprocessing import StandardScaler

# データの正規化（平均0, 標準偏差1）
scaled_clients = dropped_clients.copy()
scaled_columns = ['age_of_company', 'capital', 'employee', 'average_employee_age'] 
scaled_clients[scaled_columns] = StandardScaler().fit_transform(scaled_clients[scaled_columns])
```

以下の表がその結果になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/e70e7372-3bae-6ce4-4850-21f92f9fbb65.png)



<h3>③階層クラスター分析（1回目）</h3>
ここから顧客をクラスタリングしていきます。今回はウォード法で分析を行いました。

```python:clustering.py
import matplotlib.pyplot as plt
import japanize_matplotlib
import seaborn as sns
from IPython.display import display
sns.set(style='whitegrid', font="IPAexGothic")
from scipy.cluster import hierarchy

# 距離計算
dist = hierarchy.distance.pdist(scaled_clients, metric='euclidean')

# クラスタリング
linkage = hierarchy.linkage(dist, method='ward')

# デンドログラム
fig, ax = plt.subplots(figsize=(5,13))
ax = hierarchy.dendrogram(Z=linkage, orientation='right', labels=scaled_clients.index)

fig.show()
```

樹形図（デンドログラム）は以下になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/6d634e76-0eb2-9131-7889-a8b1de837973.png)
<small>※念のため企業名はモザイクにしております。</small>

<br>

ひとまず距離50でクラスタリングしてみます。

```python:clustering.py
clusters = hierarchy.fcluster(linkage, 50, criterion='distance')
clustered_clients = dropped_clients.copy()
clustered_clients['cluster'] = clusters
```

樹形図（デンドログラム）上で表すと以下のような区分けです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/21165a75-feee-9b8f-a71f-4c3895d389a6.png)


<h3>④各クラスターの傾向分析（1回目）</h3>

3クラスターに分割できたので、各クラスターの中身を見ながら傾向を探ったところ、以下が判明しました。

<br>

【クラスター１（グラフ下部の緑）：10.3%（16/154社）】

・全16社が東京都以外の会社
<br>

【クラスター２（グラフ中部の赤）：64.2%（99/154社）】

・全99社のうち97社が東京都の会社
・全99社のうち92社がIT企業
<br>

【クラスター３（グラフ上部の赤）：25.3%（39/154社）】

・全39社のうち34社が東京都の会社
・全39社がIT企業ではない


<br>


つまり、<strong>東京の企業かどうか、IT企業かどうかで分類分けされている</strong>ようです。


>顧客の最大セグメントは「東京都のIT企業」

<br>

<h3>⑤階層クラスター分析（2回目）</h3>

より細かな傾向があるかもしれないので、今度は東京都のIT企業（全90社）に絞って、再び階層クラスター分析を試みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/ac253131-1a3a-5800-a4fd-2d913f977e16.png)

手法は先ほどと同様にウォード法を用いました。

```python:clustering2.py
dist = hierarchy.distance.pdist(tokyo_it_clients, metric='euclidean')

# クラスタリング
linkage2 = hierarchy.linkage(dist, method='ward')

# デンドログラム
fig, ax = plt.subplots(figsize=(5,13))
ax = hierarchy.dendrogram(Z=linkage2, orientation='right', labels=tokyo_it_clients.index)

fig.show()
```

樹形図（デンドログラム）は以下になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/713dd901-aa35-1fd8-d876-d4858781127a.png)
<small>※念のため企業名はモザイクにしております。</small>

<br>

今度は距離4でクラスタリングしてみます。

```python:clustering.py
clusters2 = hierarchy.fcluster(linkage2, 4, criterion='distance')
clustered_toyo_it_clients = dropped_clients[(dropped_clients['prefecture_code'] == 13) & (dropped_clients['business_category'] == 1)].copy()
clustered_toyo_it_clients['cluster'] = clusters2
```

<br>
樹形図（デンドログラム）上で表すと以下のような区分けです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940809/30fc56ff-234c-2867-4e99-b885d3e30a42.png)


<h3>⑥各クラスターの傾向分析（2回目）</h3>

5クラスターに分割できたので、各クラスターの中身を見ながら傾向を探ったところ、以下が判明しました。

<br>


【クラスター１（グラフ最下部の緑）：4.4%（4/90社）】
・すべて資本金200億円以上
・すべて創業23年未満

<br>

【クラスター２（グラフ下部の赤）：30.0%（27/90社）】
・すべて資本金200億円未満
・すべて創業23年未満
・すべて非上場
・全27社のうち23社が平均年齢31歳未満
<br>

【クラスター３（グラフ中部の水色）：23.3%（21/90社）】
・すべて資本金200億円未満
・すべて創業23年未満
・すべて上場（クラスター2,4,5は全て非上場）
<br>

【クラスター４（グラフ上部の水色）：36.7%（33/90社）】
・すべて資本金200億円未満
・すべて創業23年未満
・すべて非上場
・すべて平均年齢31歳以上
<br>
	
【クラスター５（グラフ最上部の水色）：5.6%（5/90社）】
・すべて資本金200億円未満
・すべて創業年数23年以上

<br>



つまり、<strong>資本金200億円未満かどうか、創業23年未満かどうかで分類分け</strong>されており、90%を占める「資本金200億円かつ創業23年未満の企業」（クラスター2,3,4）は非上場かどうか・平均年齢31歳以上かどうかで細かく3クラスターに分かれていることが分かりました。

但しクラスター2,3,4はほぼ同数の企業が分類されているので、顧客の特徴として非上場かどうか・平均年齢31歳以上かどうかは「この採用選考手法を導入するかどうか」にそこまで影響しないのではないかと推察します。


>「東京都のIT企業」顧客の最大セグメントは「資本金200億円未満で創業23年未満の企業」


※とはいえ今回の顧客に限らず、大多数のIT企業が「資本金200億円未満で創業23年未満」であることは推測できるので、割と当たり前のことに過ぎないかもしれません…。



<h2>まとめ</h2>

以上のように、階層クラスター分析（ウォード法）によって以下のことが分かりました。

<ul>
<li><strong>東京都</strong>にある企業が85.0%（131/154社）</li>
<li>そのうち<strong>IT企業</strong>が68.7%（90/131社）</li>
<li>そのうち<strong>資本金200億円未満</strong>の企業が95.5%（86/90社）</li>
<li>そのうち<strong>創業23年未満</strong>の企業が94.2%（81/86社）</li>
</ul>

つまり過半数以上（81/154社）の顧客が「東京都にある資本金200億円未満・創業23年未満のIT企業」であることが判明しました。これから営業活動を行っていく際は、この条件にあてはまる企業にアプローチした方が効率が良いと推察できます。

とはいえ今回は教師なし学習の範疇であったため、見込み客の予測へと繋げていくためには以下例のような<strong>顧客データのラベリングを基にした教師あり学習</strong>を行う必要がありそうです。
<br>

<ul>
<li>弊社ツールの導入有無によるラベリング　⇒　<strong>導入有無を予測する分類モデル<strong></li>
<li>売上の金額によるラベリング　⇒　<strong>売上額を予測する回帰モデル<strong></li>
</ul>

これらの分析は弊社の顧客データが増えてきた段階でまた実施してみようと思います！