新年あけましておめでとうございます。
本年もよろしくお願いします。
さて、今回は昨年からの続きで、代表的な分析手法である「クラスター分析」を試したいと思います。
分析するデータ
前回までと同様にNPB公式サイトに掲載された2005年から2021年までの規定打席到達者のデータを利用します。
取得方法については、以前の記事をご覧下さい。

分析手法
今回はクラスター分析を行います。クラスター分析はざっくり以下の様なものです。
クラスター分析とは、異なるものが混ざりあっている集団の中から互いに似たものを集めて集落(クラスター)を作り、対象を分類するという方法の総称です。
「対象」というのは人間とは限らず、企業や商品や地域や、そして時には質問項目を分類する場合もあることに注意してください。このクラスター分析を用いると、標準化された手続に従って対象の分類ができるため、マーケティングリサーチにおいてはポジショニング確認を目的としたブランドの分類や、イメージワードの分類、生活者のセグメンテーションなどに用いられます。
調査データに対してクラスター分析を実行することで、メーカーサイドの視点に立ったブランドの分類や、デモグラフィック要因による生活者の分類とは異なった「生活者サイドの視点に立った分類」を発見できます。
出典:マクロミル
仮定
今回は、分析するデータの中から、「打率」と「本塁打」の抽出してクラスター分析を行いますので、ざっくり以下の4つの分類にデータが分類されると想定しています。
- 打率が高く、本塁打も多い「強打者タイプ」
- 打率が高く、本塁打が少ない「功打者タイプ」
- 打率が低く、本塁打が多い「一発屋タイプ」
- 打率が低く、本塁打が少ない「守備の人タイプ」
コーディング
今回使用するライブラリをまとめて読み込みます。
# ライブラリの読み込み
import pandas as pd
import numpy as np
from sklearn import datasets,preprocessing
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
今回使用するデータを読み込みます。
# データの読み込み
df = pd.read_csv("2005-2021_batter_all.csv")
読み込んだデータの中から使用する列を抜き出します。ついでに、どんなデータが抽出できたか確認します。
# データの整形
X = df[["打率","本塁打"]]
X.describe()
[describeの出力結果]
打率 | 本塁打 | |
count | 990.000000 | 990.000000 |
mean | 0.280890 | 14.949495 |
std | 0.027576 | 11.019583 |
min | 0.204000 | 0.000000 |
25% | 0.262000 | 6.000000 |
50% | 0.279000 | 13.000000 |
75% | 0.300000 | 22.000000 |
max | 0.378000 | 60.000000 |
打率と本塁打で単位が一致していないことが、この後の分析に支障を来すので、正規化したうえでクラスタリングします。
# データを正規化
sc = preprocessing.StandardScaler()
sc.fit(X)
X_norm = sc.transform(X)
# 正規化したデータフレームを使ってクラスタリング
cls = KMeans(n_clusters=4)
result = cls.fit(X_norm)
クラスタリングした結果をグラフに出力します。
# グラフを描画
plt.figure(figsize=(10,10))
plt.scatter(X_norm[:,0],X_norm[:,1], c=result.labels_)
plt.scatter(result.cluster_centers_[:,0],result.cluster_centers_[:,1],s=250, marker="*",c="red")
plt.show()
[出力結果]

考察
- おおよそ仮定通り綺麗に4つに分類されました。
- 一方で、予想外だったのは本塁打が少なくとも打率が飛び抜けて高ければ「強打者」タイプに分類されたことです。
その他
出力結果中で、赤丸で囲った本塁打が飛び抜けているデータは2013年のバレンティン選手、青丸で囲った打率が飛び抜けているデータは2008年の内川聖一選手のデータになります。
それぞれ、とんでもない記録であることがグラフから読み取れます。