scikit-learnで2016年夏の代表校をクラスタリング

# はじめに

夏季休暇ということでお勉強がてら `scikit-learn` を触ってみました。夏休みの自由研究といったところです。初心者的な内容ですがご容赦ください。

本当は機械学習的なことがやりたかったんですが、知識もデータも不足しているので出来そうなことから着手。ちょうど夏の高校野球甲子園大会が（個人的に）盛り上がっているところなので地方大会のデータを使って代表校をクラスタリングしてみることにしました。

# データの準備

個人成績などのデータを集めてくれば色々分析できそうですが、まずはチーム打率、防御率など基本的なデータを使ってみることにしました。

## 打撃成績

[このサイト](http://a-bis.net/bbk/kokoyakyu/3742) を参考にして元データを作成。各代表校の地方大会の打率、本塁打、犠打、盗塁数がまとまっています。なんか１校だけ本塁打数が飛び抜けてますね。
ちなみに、よく見ると代表校がちゃんと県コード順に並んでます。

https://github.com/radiocat/study-sklearn/blob/master/hs-bb/batting-2016.csv

## 投手成績

[このサイト](http://koshien.site/wp/2016/08/05/%E9%AB%98%E6%A0%A1%E9%87%8E%E7%90%83%E5%A4%8F%E3%81%AE%E7%94%B2%E5%AD%90%E5%9C%92%E5%87%BA%E5%A0%B4%E6%A0%A1%E6%8A%95%E6%89%8B%E6%88%90%E7%B8%BE/) を参考にして元データを作成。各代表校の地方大会での主戦投手、投球回、失点、防御率がまとまっています。１人で６割以上の投球回数を投げていない場合は２人または３人の投手で計算しているようです。主戦投手は人数をカウントして別項目に追加しました。

https://github.com/radiocat/study-sklearn/blob/master/hs-bb/pitching-2016.csv

# クラスタリング

クラスタ数はとりあえず `5` にしました。根拠は特にないです。
アルゴリズムは `k-means` を使います。これが良いというよりあえて他を選ぶ知識が無いので…

## 打撃成績

```py
#coding:utf-8
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

dataframe = pd.read_csv('batting-2016.csv')

array = np.array([dataframe['試合数'].tolist(),
    dataframe['打率'].tolist(),
    dataframe['本塁打'].tolist(),
    dataframe['犠打'].tolist(),
    dataframe['盗塁'].tolist()
    ], np.float)
array = array.T

predict = KMeans(n_clusters=5).fit_predict(array)
print(predict)
```

## 投手成績

```py
#coding:utf-8
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

dataframe = pd.read_csv('pitching-2016.csv')

array = np.array([dataframe['投手数'].tolist(),
    dataframe['投球回数'].tolist(),
    dataframe['失点'].tolist(),
    dataframe['防御率'].tolist()
    ], np.float)
array = array.T

predict = KMeans(n_clusters=5).fit_predict(array)
print(predict)
```

## 総合成績

打撃と投手成績を合わせてみました。

```py
#coding:utf-8
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

batting_dataframe = pd.read_csv('batting-2016.csv')
pitching_dataframe = pd.read_csv('pitching-2016.csv')

array = np.array([batting_dataframe['試合数'].tolist(),
    batting_dataframe['打率'].tolist(),
    batting_dataframe['本塁打'].tolist(),
    batting_dataframe['犠打'].tolist(),
    batting_dataframe['盗塁'].tolist(),
    pitching_dataframe['投手数'].tolist(),
    pitching_dataframe['投球回数'].tolist(),
    pitching_dataframe['失点'].tolist(),
    pitching_dataframe['防御率'].tolist()
    ], np.float)
array = array.T

predict = KMeans(n_clusters=5).fit_predict(array)
print(predict)
```

## 結果

| 学校名 | 打撃 | 投手 | 総合 |
|:-:|:-:|:-:|:-:|
| クラーク記念国際 | 1 | 2 | 2 |
| 北海 | 2 | 0 | 1 |
| 八戸学院光星 | 3 | 2 | 3 |
| 盛岡大付 | 0 | 1 | 0 |
| 東北 | 4 | 0 | 1 |
| 大曲工 | 0 | 2 | 2 |
| 鶴岡東 | 1 | 4 | 0 |
| 聖光学院 | 0 | 3 | 0 |
| 常総学院 | 0 | 1 | 2 |
| 作新学院 | 0 | 3 | 0 |
| 前橋育英 | 0 | 0 | 1 |
| 花咲徳栄 | 1 | 1 | 3 |
| 木更津総合 | 4 | 2 | 1 |
| 関東一 | 1 | 2 | 2 |
| 八王子 | 3 | 3 | 4 |
| 横浜 | 1 | 2 | 2 |
| 中越 | 3 | 3 | 4 |
| 富山第一 | 4 | 4 | 3 |
| 星稜 | 1 | 3 | 0 |
| 北陸 | 0 | 3 | 0 |
| 山梨学院 | 0 | 4 | 0 |
| 佐久長聖 | 1 | 1 | 2 |
| 中京 | 0 | 4 | 0 |
| 常葉菊川 | 3 | 1 | 3 |
| 東邦 | 3 | 1 | 4 |
| いなべ総合 | 0 | 4 | 0 |
| 近江 | 0 | 1 | 2 |
| 京都翔英 | 0 | 1 | 2 |
| 履正社 | 1 | 0 | 1 |
| 市尼崎 | 4 | 0 | 1 |
| 智弁学園 | 1 | 2 | 2 |
| 市和歌山 | 4 | 2 | 3 |
| 境 | 0 | 3 | 0 |
| 出雲 | 4 | 1 | 3 |
| 創志学園 | 0 | 1 | 2 |
| 広島新庄 | 4 | 2 | 3 |
| 高川学園 | 3 | 0 | 3 |
| 鳴門 | 1 | 4 | 0 |
| 尽誠学園 | 4 | 3 | 3 |
| 松山聖陵 | 4 | 2 | 3 |
| 明徳義塾 | 0 | 4 | 0 |
| 九州国際大附 | 0 | 2 | 2 |
| 唐津商 | 1 | 3 | 2 |
| 長崎商 | 1 | 2 | 2 |
| 秀岳館 | 3 | 4 | 4 |
| 大分 | 0 | 3 | 2 |
| 日南学園 | 0 | 4 | 0 |
| 樟南 | 2 | 2 | 1 |
| 嘉手納 | 1 | 2 | 2 |


# まとめ

色々ツッコミはありそうですが、データの傾向が数値的に似ているというだけなので0と4のどちらが強いとかではなさそうです。まあ地方大会のデータなんて甲子園では全く別モノですし深く追求しても仕方ないです。

優勝校を予想するとかが目的ではないので内容についてはこれ以上は言及しませんが、１試合平均の打率などに計算し直したり、主戦投手数が複数人の場合はこれも平均にするとか投手ごとの投球回数などの情報を調べてもっと細かい数値を出してクラスタリングすればまた違った結果が得られそうな気はします。この辺りがデータサイエンスの重要な領域なんだと思いますが今回はここまでにしたいと思います。