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

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

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

前回は「Google Colab」でのファイルの読み込みを試しました。今回は一歩進んでPythonでのデータ準備作業と簡単な計算に挑戦してみます。前回同様worldfootball.netから取得したデータを使って、プレミアリーグに所属する選手の平均身長および平均年齢を求めてみようと思います。具体的な統計解析の手法に関しては、「Pythonで理解する統計解析の基礎」を元に学んでいきます。

 

データの準備

結論から言うと、Pythonを使って平均を求めること自体は簡単でしたが、データを扱える形に変換(=準備)するところがかなり大変でした。今後データ分析する上でも、この部分が肝になりそうです。

繰り返しになりますが、今回も前回同様下記データを使用します。平均身長と平均年齢を求めるに当たって必要な準備は、1.余計なデータを取り除く2.身長から'cm'を取り除き数字として読み込む3.生年月日から年齢を算出する、の3ステップとなります。

f:id:virgilvd:20181101001636p:plain

Pandasを使って読み込んだデータの大きさは、shapeと呼ばれるインスタンス変数(インスタンス変数が何かは詳しく分かっていません。。)で確認できるとのことなので確認しておくと、

f:id:virgilvd:20181103212530p:plain

となり、574レコード、5カラム(Player, Team, born, Height, Position)のデータだと分かります。

・余計なデータを取り除く

前述の画像内「Kyle Taylor」列を見ても分かりますが、今回扱うデータにはところどころに「???」という値が入っています。まずは、この「???」を取り除いていきます。

パッと見た範囲でHeight列に「???」がありそうなので、まずはHeight列の「???」を確認します。特定の文字列を含む行を検索するstr.contains( )を利用してみます。

df[df['Height'].str.contains('\?\?\?')]

ここで気をつけたいのが、「???」ではなく「\?\?\?」で検索している点です。str.contains( )は正規表現と呼ばれる表現に対応しているらしく、?はその正規表現で使われる文字なのだそうです。そのため、今回は文字としての?であることを示すために\?と表記します。(これに気づかずハマりました。。)

f:id:virgilvd:20181103213648p:plain

 実行してみるとHeight列が「???」となっているレコードは、13レコードあることが分かります。(ここでborn列にも「???」が出てきているので、born列でも同様に確認してみると、born列は上画像の1レコードしか無いことが分かるので今回は無視します。)

余計なデータが分かったところで、それらを取り除いた今回の分析用のデータを作っていきます。

df2=df[~df['Height'].str.contains('\?\?\?')]

shapeを使ってデータの大きさを確認すると、最初のデータから13レコード取り除かれて561レコードになっていることが分かります。これで1つ目のステップは終了です。

f:id:virgilvd:20181103214942p:plain

・身長から'cm'を取り除き数字として読み込む

 文字列から特定の文字を置換する場合は、.str.replace( )を使用するそうです。

df['Height'] = df ['Height'].str.replace(' cm','')

実行して確認してみると、無事に'cm'が置換され消えていることが分かります。

f:id:virgilvd:20181103215747p:plain

ただまだこれだとHeigt列は文字列として認識されている(=計算ができない)ので、数字の型へと変換していきます。変換にはastype( )を利用し、変換したデータの確認にはdtypesを利用します。

df2 = df2.astype({'Height':'int64'})

f:id:virgilvd:20181103220105p:plain

これで無事にHeight列が数字の型(int64=整数)へと変換されました。2つ目のステップはこれで終了です。

・生年月日から年齢を算出する

最後のステップは生年月日から年齢を算出して、新しく年齢の列をデータに加えます。年齢の算出に当たっては下記サイトのソースを利用させていただきました。

qiita.com

born列は現在文字列として認識されているので、まずは時間の型へ変換。変換にはpandas.to_datetime( )を利用します。

df2['born']=pd.to_datetime(df2['born'])

f:id:virgilvd:20181103220743p:plain

これで年齢を算出するための準備が出来たので、上記サイトの関数をそのまま利用します。関数の意味としては、生年月日と今日の日付を8桁の整数に変換(2018年11月01日→20181101)し、それらの差分を整数に変換した際の西暦の部分(すなわち10000)で割ることで年齢を算出しています。

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)

この関数を利用し、born列から各選手の年齢を求め、Age列として追加します。これもコードをそのまま利用させていただきます。(Lambda関数に関しては、まだよく分かっていませんがここでは深く入り込まないことにします)

df2['Age']=df2['born'].apply(lambda date: getAge(date))

f:id:virgilvd:20181103221821p:plain

無事に選手の年齢を表すAge列が追加されています。これでようやくデータ分析を行う準備が整いました。

 

プレミアリーグの平均身長・年齢を計算する

ここからいよいよPythonを使った計算を行っていきます。以降は「Pythonで理解する統計解析の基礎」に乗っ取って進めていきたいと思います。

Pythonで理解する統計解析の基礎」では、NumPyと呼ばれるPythonのライブラリを中心に数値計算を行なっていくとのことなので、まずは NumPyをインポートします。

import NumPy as np

対象となるデータをNumPyで計算できる形にするため、NumPyのarrayというデータ構造にして保存します。

height = np.array(df2['Height'])

f:id:virgilvd:20181103223906p:plain

Pandasのデータ構造であるDataFrameでも計算可能なことを確認するため、選手名をインデックスにしたデータも作成しておきます。

height_df = pd.DataFrame({'身長':height},index=df2['Player'])

f:id:virgilvd:20181103225343p:plain

NumPyの関数mean( )を使用して、平均を求めます。

np.mean(height)

DateFrameでは、meanメソッドを使用して求められるそうです。(関数とメソッドの違いについても追々勉強したいと思います。)

height_df.mean()

f:id:virgilvd:20181103225921p:plain

これで、プレミアリーグ所属選手561人の平均身長が182.84cmであることが分かりました。もう少し高いかと思っていましたが、意外とこのくらいなんですね。medianメソッドを使用して中央値も出して見ましたが、こちらも183.0cmと大きく変わりませんでした。

同様に年齢の平均値も計算してみます。

f:id:virgilvd:20181103230321p:plain

こちらに関しては、若手からベテランまで幅広い年齢層で活躍していることを考えるとまぁ妥当かなと言う感じです。こちらも中央値は26.0と、平均値とほぼ一緒の値でした。

今回はPythonを使ってデータの準備から簡単な計算までを行ってみました。作業途中何度かはまってしまいましたが、こうしてコツコツ続けていくことで実力アップしていければと思います。

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