Python 連携によるクラスター解析

## はじめに
Yellowfin では[高度な関数](https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=2293963)を利用するなどして、様々な分析や統計解析を行うことができます。あるいは、R や Python などの外部機能と連携することで、世の中に普及するライブラリなどを活用して分析することも可能です。
本記事の中では、Python と連携して K-Means によるクラスター解析を行い、解析結果を Yellowfin で可視化する流れを紹介したいと思います。

## 環境準備と前提
Python に必要なパッケージをインストールします。
|パッケージ|今回の用途|インストールコマンド|
|---|---|---|
|psycog2|PostgreSql 接続|pip install psycopg2|
|pandas|データフレームの扱い|pip install pandas|
|numpy|配列の扱い|pip install numpy|
|scikit-learn|クラスター解析|pip install scikit-learn|

処理の全容は以下の通りです。
1. データの準備
2. 販売データをクラスター分析
3. Yellowfin を使って解析結果を含むデータを可視化

## 1. データの準備
分析対象のサンプルデータとしては、カリフォルニア大学アーバイン校が運用する [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml/index.php) で公開されている Wholesale customers Data Set を使用します。卸売業者の販売データで、購入状況から顧客をクラスター分けする目的には適したデータです。
上記から入手した CSV データをそのままデータベースのテーブルにインポートします。結果、以下のようなテーブル構造になります。
|列名|データの内容|
|---|---|
|channel|販売チャネルコード|
|region|地域コード|
|fresh|生鮮食品の販売データ|
|milk|牛乳の販売データ|
|grocery|食料品・雑貨の販売データ|
|frozen|冷凍食品データの内容の販売データ|
|detergents_paper|洗浄紙の販売データ|
|delicassen|惣菜の販売データ|

正確な日本語が選択できているか否か少々疑問ですが、そこは気にせず進みましょう。

## 2. 販売データをクラスター分析
上記データを読み込んで、クラスター分析する一連の処理を Python で記述します。
K-Means と呼ばれる手法を使ってデータをクラスター分けします。K-Means は非階層型のクラスター分析の手法で、近い属性をもつデータどうしを同じグループにまとめます。販売分析やマーケティング分析などにしばしば使われる手法です。
非階層型と階層型のイメージはおおよそ以下のような感じです（イメージ♪イメージ♪あくまでもイメージ♫）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/1f90719e-07c1-bb21-74eb-382f54caaf80.png)

では、Python で記述していきます。

Postgresql のテーブルに接続して、該当テーブルから取得したデータを pandas のデータフレームに格納します。
```python:データフレーム
import psycopg2
import pandas as pd
conn = psycopg2.connect("dbname=demo user=postgres password=password host=localhost port=5432")
query = """SELECT fresh, milk, grocery, frozen, detergents_paper, delicassen FROM wholesale"""
df = pd.read_sql(query, con=conn)
```

データフレームから計算に使用する列を抽出して、numpy のリストに変換し、最後に行と列の入れ替えを行います。
```python:リスト
import numpy as np
arr = np.array([df['fresh'].tolist(),
                df['milk'].tolist(),
                df['grocery'].tolist(),
                df['frozen'].tolist(),
                df['milk'].tolist(),
                df['detergents_paper'].tolist(),
                df['delicassen'].tolist()
                ], np.int32)
arr = arr.T
```

クラスター解析を実行して、5 つのクラスターに分類します。
分類結果を受けて、クラスタの情報を、データフレームに新しい列として挿入します。
```python:解析
from sklearn.cluster import KMeans
pred = KMeans(n_clusters=5).fit_predict(arr)
df['cluster_group']=pred
```

コード全体は以下の通りです。
```python:全容
import psycopg2
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

#Postgresqlのテーブルに接続して、取得したデータをpandasのデータフレームに格納
conn = psycopg2.connect("dbname=demo user=postgres password=password host=localhost port=5432")
query = """SELECT fresh, milk, grocery, frozen, detergents_paper, delicassen FROM wholesale"""
df = pd.read_sql(query, con=conn)

#データフレームから計算に使用する列を抽出して、numpyのリストに変換
arr = np.array([df['fresh'].tolist(),
                df['milk'].tolist(),
                df['grocery'].tolist(),
                df['frozen'].tolist(),
                df['milk'].tolist(),
                df['detergents_paper'].tolist(),
                df['delicassen'].tolist()
                ], np.int32)

#行と列を入れ替え
arr = arr.T

#クラスタ分析を実行して、クラスター単位に区分け
pred = KMeans(n_clusters=5).fit_predict(arr)

#クラスタグループの情報を、データフレームに新しい列として挿入
df['cluster_group']=pred

# 取り急ぎ CSV ファイルに結果を出力
csv_writer = df.to_csv('Wholesale.csv')
```
## Yellowfin を使って解析結果を含むデータを可視化
出力結果をデータベースのテーブルに取り込みます。これで、クラスター単位に区分けされた情報を Yellowfin で活用できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/96db73b0-2ec5-9c24-54be-ead62fb493d2.png)

Yellowfin で積み上げ棒グラフを作成し、クラスターごとのカテゴリー別売上を可視化した例が以下になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/a73de98b-c761-22d4-0aa6-f02739935b41.png)

## 最後に
Python で使用できる様々なライブラリを活用することで、Yellowfin 単体では実現できない様々な分析が可能になります。
[『Python 連携による形態素解析』]( https://qiita.com/ExtremeCarvFJ/items/f8932b9364664458fa53)の記事で紹介した、形態素解析などもその一例です。
今後も継続的に、外部機能との連携を模索していこうと思います。

では皆様、良いデータ分析を! See you then! Cheers!!

## 参考記事

https://pythondatascience.plavox.info/scikit-learn/%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%88%86%E6%9E%90-k-means