サッカーを通じて観戦力と分析力を上げていくブログ

基本的にはサッカー×データに関して試してみたことをまとめています。最近はもっぱらPythonを使った可視化中心。時々自分の好きなガジェットも。

【データ分析 × Python】プレミアリーグ所属選手の身長・年齢を可視化してみる

前回に引き続き「Pythonで理解する統計解析の基礎」を参考にして、Pythonを使ったデータ分析の手法を学んでいきます。今回はプレミアリーグ所属選手の身長と年齢を可視化して、より分かりやすく理解出来るようにしてみます。

 

データの概要を掴む

前回記事プレミアリーグ所属選手の平均身長および平均年齢が、それぞれ182.84cmと26歳であることが分かりました。しかし、こういったいわゆる代表値と呼ばれる値だけでは、全体感を掴むことが出来ません。そこで、データのばらつきを表す標準偏差や四分位範囲などを見てみる必要があるのですが、PandasのDataFrameにはdscribeという便利なメソッドがあるようです。これを使うとデータの概要を表すいくつかの値を一発で求めることが出来ます。

height_df.describe()

f:id:virgilvd:20181104232719p:plain

ここで、countがレコード数、meanが平均値、stdが標準偏差、minが最小値、25%が第1四分位点、50%が第2四分位点(中央値)、75%が第3四分位点、maxが最大値を表しています。ここからプレミアリーグ所属選手は、163cmから201cmの選手まで在籍しており、多くの選手が182cm前後であることが分かります。

年齢について同様に算出したものが下記になります。

f:id:virgilvd:20181104233422p:plain

この結果からは、17歳から39歳の選手までが在籍しているものの、なんとなく20代よりの分布になっていることが分かります。

 

度数分布表でより詳しく概要を掴む

discribeメソッドによってプレミアリーグ所属選手の身長や年齢がざっくりどうなっているのかは分かりました。ここからはより細かくデータの散らばりをみるために度数分布表を作成して見てみます。

度数分布表において、区間のことを階級、各階級の数を度数、各区間の幅を級数、階級の数を級数と呼ぶそうです。ここで、プレミアリーグ所属選手の身長の最小値と最大値はそれぞれ163cmと201cmだったので、150cmから210cmまでの60cmを階級幅5cm、階級数12で分類したいと思います。度数の配列をNumPyのnp.histgramを使用して求めてみます。(ソースコードは「Pythonで理解する統計解析の基礎」を参考にしていますが、「freq, _ = 〜」の「, _」部分の意味は謎です)

freq, _ = np.histogram(height, bins=12, range=(150, 210))

f:id:virgilvd:20181105222042p:plain

作成した度数は、Pandasで扱うデータ形式DataFrameに格納していきます。細かい部分の理解は先延ばしにして、まずはサンプルを真似してやって見ます。

freq_class = [f'{i}~{i+5}' for i in range(150, 210, 5)]
freq_dist_df = pd.DataFrame({'度数':freq},index=pd.Index(freq_class, name='階級'))
freq_dist_df

f:id:virgilvd:20181105223108p:plain

これで度数分布表は完成ですが、ここに更に階級値相対度数累積相対度数を格納し、より理解しやすい形にしてみます。

階級値(各階級を代表する値)

class_value=[(i+(i+5))//2 for i in range(150, 210, 5)]

相対度数(全データに対してその階級のデータがどの程度の割合か)

rel_freq=freq/freq.sum()

累計相対度数(相対度数の累計。np.cumsumで求められる)

cum_rel_freq=np.cumsum(rel_freq)

これらを先ほどの度数分布表に付け加えます。

freq_dist_df['階級値'] = class_value
freq_dist_df['相対度数'] = rel_freq
freq_dist_df['累積相対度数'] = cum_rel_freq
freq_dist_df = freq_dist_df[['階級値', '度数', '相対度数', '累積相対度数']]
freq_dist_df

f:id:virgilvd:20181105223843p:plain

こうしてみるとより詳細な分布が簡単に分かるようになります。約半分の選手が180cmから190cmの間に分布していることや、170cm以下の選手がほとんどいないこと、それよりも195cm以上の選手の方が多いことなどです。

同様に年齢についても算出すると下記のようになります。

f:id:virgilvd:20181105230520p:plain

こうして見ると、25歳から30歳までの選手が大多数を占めていることが分かります。20歳以下の選手はたった5%しかいないんですね。 

 

ヒストグラムで分布を可視化してみる

最後に今回の目的でもある「グラフで分かりやすく可視化する」作業を行ってみたいと思います。度数分布表から得られる情報となんら変わりはないですが、先ほどのデータを視覚的に一発で分かるヒストグラムの形で表示させてみます。

ここで登場するのがMatplotlibというライブラリ。 これまで使ってきたPandas、NumPyとあわせて統計解析における三種の神器なのだそうです。早速Matplotlabをインポートしていきます。

import matplotlib.pyplot as plt
%matplotlib inline

ここで2行目の「%matplotlib inline」はグラフを表示するために必要とのことです。

グラフを描画するに当たって知らない部分や分からない部分が多々出てきましたが、まずは描画することを目標にコードを描いてみます。

fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
freq, _, _ = ax.hist(height, bins=12, range=(150, 210))
ax.set_xlabel('height')
ax.set_ylabel('count')
ax.set_xticks(np.linspace(150, 210, 12+1))
ax.set_yticks(np.arange(0, freq.max()+10, 10))
plt.show()

f:id:virgilvd:20181106234551p:plain

前述のコードを1行ずつ記載しても表示されなかったり、各関数・メソッドの引数を理解していなかったりするのですが、とりあえず描画には成功しました。グラフ化することでよりデータの傾向が簡単に分かるようになりました。

年齢についても同様にヒストグラムで描画してみます。

f:id:virgilvd:20181106235928p:plain

こちらも同様に、25歳から30歳の選手が突出して多いことが一発で分かるようになりました。長くなってきたので、今回は一旦ここまでにします。次回は、今回飛ばし飛ばしで行った、グラフの描画について深掘りしていけたらと思います。

戦術や分析に関して、こういう見方もあるよ、こうして見た方がいいよ、などご意見等ありましたら、コメントで教えていただけると幸いです。ぜひよろしくお願いいたします!