大谷翔平選手で機械学習！(クラスタリング)(投手編)

##１．前口上
大リーグで活躍している大谷翔平選手。目を見張る大活躍だ。
その大谷選手をテーマに機械学習を学べば、興味が持てて、身につくだろうということで、やってみた。

今回は、投手編。使用するデータは大リーグMLBが提供しているこちらのサイト。とっても充実した良いサイトだ。
https://baseballsavant.mlb.com/

データ分析には、GoogleのColaboratoryを使用した。自分のマシンより良いスペックのマシンが使えるのは嬉しい。

##２．分析手法
日本では大谷投手の球速が話題になるけれど、大リーグでは回転数も注目されている。そこで、球速と回転数を使って、機械学習（教師なし、クラスタリング）をやってみよう。

まずは、先ほどのBaseball Savantのサイトから、2017年の投手のデータを集める。球種はデータが最も多いフォーシーム（いわゆるストレートの速球）。

大谷投手のデータだけは、2018年4月のデータを使った。

球速は大リーグで重宝されている「打者が体感する球速」を使ってみよう。これは、球を投げる際のリリース・ポイントが考慮されている球速で、打者に近いところでリリースされれば、その分だけ、打者との距離が短くなって、球を速く感じるということらしい。

球速も回転数も、対象期間の平均値を使用した。

##３．クラスタリングの準備
データはpitch2017.csvという名前で保存して、Colaboratoryにアップロードする。

```
from google.colab import files
upload = files.upload()
```

ファイル選択の画面が出るので、アップロードするファイルを選ぶことになる。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/76072/3783eb08-5d98-36c7-e277-479ff246628b.png)


念のため、確認すると、アップロードできたことが分かる。

```
!ls
```

![02.png](https://qiita-image-store.s3.amazonaws.com/0/76072/6dd44ed9-1163-a80c-232e-32795dd8fa38.png)


ここから先はColaboratoryを使わない場合も同じ。Pandasを使って分析を進める。

```
import pandas as pd
df = pd.read_csv("pitch2017.csv")
df
```

対象とした33投手の名前とデータが分かる。（番号はゼロ始まり）
大谷投手のデータは最後に加えている。

![03.png](https://qiita-image-store.s3.amazonaws.com/0/76072/c31e4782-6271-1af5-5463-82d4aefb7920.png)
![04.png](https://qiita-image-store.s3.amazonaws.com/0/76072/d4cc2421-e431-144f-dc07-f31a45206818.png)

まずは、散布図で見てみよう。

```
df.plot(kind='scatter',x='Avg Perceived Speed (mph)',y='Avg Spin Rate (rpm)')
```

![05.png](https://qiita-image-store.s3.amazonaws.com/0/76072/733b0eb0-5a80-e411-a20d-25f46b0bf72e.png)


##４．クラスタリング（失敗例）
まず、失敗した例から見ていこう。
データ加工しないで、クラスタリングをしてみる。
クラスタリングの結果はresultsに格納する。

```
from sklearn.cluster import KMeans
km=KMeans(n_clusters=3,
         init='k-means++',
         random_state=0)
X=df[['Avg Perceived Speed (mph)','Avg Spin Rate (rpm)']]
km.fit(X)
y=km.labels_
df['results']=y
df.tail()
```

![06.png](https://qiita-image-store.s3.amazonaws.com/0/76072/48a29668-facd-b390-e614-d622c5adcbbc.png)

結果を散布図で見てみよう。

```
import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==0),df['Avg Spin Rate (rpm)'].where(y==0),c="r",s=40)
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==1),df['Avg Spin Rate (rpm)'].where(y==1),c="b",s=40)
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==2),df['Avg Spin Rate (rpm)'].where(y==2),c="g",s=40)
plt.xlabel('Avg Perceived Speed (mph)')
plt.ylabel('Avg Spin Rate (rpm)')
```

![07.png](https://qiita-image-store.s3.amazonaws.com/0/76072/a1ae067e-cfd5-e8c0-47e6-af5a268f878f.png)


何か、変じゃないですか？
上・中・下と並んでいる。
これって、単純に回転数だけでクラスタリングされている。

球速が二桁（およそ98mph)なのに対して、回転数は四桁（およそ2,300回転）。つまり、回転数が相対的に大きいので、回転数だけでクラスタリングされている。

これじゃマズイので、標準化して、やり直そう。

##５．クラスタリング（やり直し）
まずは、関数を作って、標準化しよう。やっぱり、データの前準備が大切だ。
標準化したデータは球速A、回転数Bとしてデータフレームに追加しよう。

```
zscore=lambda x:(x-x.mean())/x.std()
df[['A','B']]=df[['Avg Perceived Speed (mph)','Avg Spin Rate (rpm)']].transform(zscore)
df.tail()
```

![12.png](https://qiita-image-store.s3.amazonaws.com/0/76072/6bf6b426-4f5a-5b13-207b-19ffb518c62e.png)

もう一度、クラスタリングして、

```
from sklearn.cluster import KMeans
km=KMeans(n_clusters=3,
         init='k-means++',
         random_state=0)
X=df[['A','B']]
km.fit(X)
y=km.labels_
df['results']=y
df.tail()
```

![09.png](https://qiita-image-store.s3.amazonaws.com/0/76072/501373d5-9737-a9d2-ca81-71705b373118.png)

プロットしてみよう。

```
plt.scatter(df['A'].where(y==0),df['B'].where(y==0),c="r",s=40)
plt.scatter(df['A'].where(y==1),df['B'].where(y==1),c="b",s=40)
plt.scatter(df['A'].where(y==2),df['B'].where(y==2),c="g",s=40)
plt.xlabel('Avg Perceived Speed')
plt.ylabel('Avg Spin Rate')
```

![10.png](https://qiita-image-store.s3.amazonaws.com/0/76072/ef5c7a2d-1b25-1fa8-fe90-a467874b0a23.png)

大谷投手は球は速いけど、回転数は多くない投手にクラスタリングされている。
（黒い星で囲まれた赤い点が大谷投手のデータ）
大谷投手と同じクラスターに含まれる投手を上げてみよう。

```
df1=df['Pitcher'].where(y==0)
df1=df1.dropna()
df1
```

![11.png](https://qiita-image-store.s3.amazonaws.com/0/76072/9ac2eee3-412b-7a4b-1084-83824d60f853.png)

##６参考データ
同じクラスターの投手をWikipediaで調べてみると、以下のようになっていた。（番号は表の番号と合わせている。説明は抜粋。）

1ノア・セス・シンダーガード（Noah Seth Syndergaard）
長身からオーバースローで投げ下ろす、平均97-98mph（約156-158km/h）・最速101.4mph（約163.2、km/h）の速球（フォーシーム・シンカー）を操るなど、平均球速は先発投手であるにもかかわらずMLB全体でもトップクラスである。また、制球も悪くない。変化球では縦に割れる平均81mph（約130km/h）カーブが一級品で、平均89mph（約143km/h）チェンジアップも投げ分ける。

7ジョセフ・ウィリアム・ケリー (Joseph William Kelly)
2015年までは、150キロ台前半から半ば (150 - 156キロ) のツーシーム (シンカーとも) が主体をなしていたが、2016年にリリーフに転向すると球速が増して、161キロまで出るようになった。変化球としては、チェンジアップ・カーブ・スライダーがある。投球スタイルとしては、ツーシーム・シンカーでゴロを量産するグラウンドボールピッチャーだったが、リリーフ転向後は三振を大量に奪うようになった。

8ホセ・アントニオ・アルバラド
96-99mphの4シームを投げるほか、カーブは80mph前半。コントロールに難あり。ベネズエラ出身。

19トーマス・ロバート・ケインリー（Thomas Robert Kahnle)
オーバースローから、最速球速100.6mph（162km/h）・平均98mph（158km/h）のフォーシームを中心に、決め球である平均90mph（145km/h）のチェンジアップ、平均87mph（140km/h）のスライダーで投球を組み立てる。

29ルイス・アマド・ガルシア（Luis Amado García)
2016年、メジャーでは17試合の登板に留まり、防御率6.46・1勝1敗・WHIP1.89と炎上して結果を残せなかった。

30ホセ・ラファエル・ディアス・ロドリゲス（Jose Rafael Diaz Rodriguez)
スリークォーターから、平均球速96 mph（約154 km/h）のフォーシーム、平均86 mph（約138 km/h）のスライダー、平均96mph（約154 km/h）のシンカー、平均90 mph（約145 km/h）のチェンジアップ、稀に平均94 mph（約151 km/h）のカッターも使用する。

球速がある一方、制球に苦しんでいる投手もいるらしい。

##７最後に
このクラスタリングが有益かどうか、僕には正直、分らない。
ただ、大谷翔平選手のピッチャーとしての位置付けを確認したかったので、ひとまず、これで良しとしよう。

なお、大リーグについて言えば、お勧めのサイトを紹介したい。
Baseball Geeksというサイトだ。
見た目も、中身も、とっても良いサイトなので、個人的に大好きなサイトだ。
https://www.baseballgeeks.jp/

大谷翔平選手が、投手としても、大リーグで活躍を続けることを祈って、本稿を終わることとする。