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

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

【データ分析 × Python】「日本のフィジカルスタンダードを変える」いわきFCのフィジカルをBMIから見てみる

2017年の天皇杯で、コンサドーレ札幌を延長戦の上に下した試合が大きな話題を呼んだいわきFC。「日本のフィジカルスタンダードを変える」ことをビジョンの一つに掲げるクラブの選手たちのフィジカルが、現在のJリーグ選手たちと比べてどのようなポジションにあるのか、 Pythonを使って調べてみたいと思います。

調査しようと思っても公開されているデータには限りがあるので、今回は公式サイトで公開されている身長・体重・生年月日とそこから導けるBMIを使って明らかにしていければと思います。

 

使用するデータ 

BMIだけではフィジカルを測りきれないことは百も承知ですが、とりあえずやって見ます。

Jリーグ選手のデータは、「Jリーグデータサイト」から日本人選手のみに絞って収集。いわきFCの選手データは、「いわきFC公式サイト」からTOP TEAM選手の情報を収集しました。今回も分析する環境は、Googleが提供するクラウド上のPython実行環境「Google Colabratory」を使用して行きます。

96lovefootball.hatenablog.com

 

データ整形とBMIの算出

Jリーグデータサイトのデータをそのまま使うと、身長と体重がスラッシュ区切りで一つの列に入ってしまっているので、分割してそれぞれ別の列に入れ直します。

まずは、PandasのDataFrameにcsvのデータを取り込みます。

import pandas as pd
df_j = pd.read_csv("/content/gdrive/My Drive/Colab Notebooks/data/J_List.csv")

f:id:virgilvd:20181216144745p:plain

str.split( )を使用して、「身長/体重」列を分割したDataFrameを作成。引数にexpand=Trueを指定しないと、リスト形式で返されてしまうので注意しましょう。

df=df_j['身長/体重'].str.split('/', expand=True)

f:id:virgilvd:20181216150508p:plain

作成した身長と体重が分かれたDataFrameに、.columsを使って列名を付けます。

df.columns = ['身長', '体重']

f:id:virgilvd:20181216150915p:plain

この作成したDataFrameを元のデータと結合し、元々あった「身長/体重」列を削除します。それぞれ.concatと.dropを使って行います。concatは引数でaxis=1、列方向での結合を指定します。

df_j = pd.concat([df_j, df], axis=1)
df_j = df_j.drop(columns='身長/体重')

f:id:virgilvd:20181216151624p:plain

最後に型の変換を行います。今の段階だと「身長」と「体重」の列は、文字列として分割されて作られているため、数字に変換してあげる必要があります。

df_j=df_j.astype({'身長': 'int64', '体重': 'int64'})

f:id:virgilvd:20181216153629p:plain

これでようやくBMIを計算できる状態になりました。BMIを算出する式は、体重(kg)/ 身長(m)×身長(m)。今回の場合Python演算子の優先順位を考慮して下記の式で求められます。(べき乗の方が、かける割るより優先的に計算される)

df_j['BMI']=df_j['体重']/(df_j['身長']/100)**2

f:id:virgilvd:20181216160051p:plain

最後に以前も使用した関数を使って、生年月日から年齢の列を作成しておきます。 

96lovefootball.hatenablog.com

df_j['生年月日']=pd.to_datetime(df5['生年月日'])
def getAge(birthday):
    today    = int(pd.to_datetime('today').strftime('%Y%m%d'))
    birthday = int(birthday.strftime('%Y%m%d'))
    return int((today - birthday) / 10000)
df_j['年齢']=df_j['生年月日'].apply(lambda date: getAge(date))

f:id:virgilvd:20181216161613p:plain
同様の作業をいわきFCのデータでも行って、準備は完了です。

 

いわきFCのフィジカルはJリーグと比べてどのレベルなのか 

まずは、いわきFC選手とJリーグ選手のデータの概要をdescribe( )で確認してみます。 

f:id:virgilvd:20181216162131p:plain

いわきFCのデータ概要

f:id:virgilvd:20181216162042p:plain

Jリーグのデータ概要

BMIの平均値を見てみると、確かにいわきFCの方が高い数値になっており、フィジカルが強そうな印象を受けます。ただJリーグBMI最小値を見てみると、18という低めの選手もいるようなので、下に引っ張られていないか確認するためヒストグラムで見てみます。

import numpy as np
import matplotlib.pyplot as plt

bmi_j = np.array(df_j['BMI'])
bmi_iwaki = np.array(df_iwaki['BMI'])

fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
freq, _, _ = ax.hist(bmi_j, bins=180, range=(15, 30),alpha=0.3, color='b')
freq, _, _ = ax.hist(bmi_iwaki, bins=180, range=(15, 30),alpha=0.3, color='r')
plt.show()

f:id:virgilvd:20181216170016p:plain

Jリーグ選手のBMI値が正規分布に近い形をしている(=特段上にも下にも引っ張られていない)ことが分かる一方で、いわきFCの選手たちも特段BMI値が高いわけではなさそうです。

今度はクラブ別に見てみるとどうでしょうか。.groupbyと.sortvaluesを使用してJクラブ別にBMIが高いクラブから順に並べて表示してみます。

df_groupby = df_j.groupby("最終所属",as_index=False)
df_groupby.mean().sort_values(by='BMI', ascending=False)

f:id:virgilvd:20181216170937p:plain

BMI平均値上位10クラブ

f:id:virgilvd:20181216171027p:plain

BMI平均値下位10クラブ

いわきFCBMI平均値23.33は、Jクラブの全体で2番目に高い数字。先の結果と合わせると、いわきFCの選手は一人一人がずば抜けてBMI値が高いわけではありませんが、Jクラブの中ではフィジカルが強い集団と行ってもいいのではないでしょうか。(アビスパのことはよく知らないのですが、アビスパもフィジカル集団なのでしょうか笑)

参考までにメッシとクリロナBMIも調べて見ましたが、(Wikipedia情報を信じると)両者ともに24を超えており、やはり日本人選手はまだまだフィジカルが弱いんだなぁと感じてしまいました。いわきFCの選手でもBMI24に達している選手はまだ少いので、これからの活躍に期待したいと思います。

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