[seaborn] Jリーグ2019年の順位表を色々グラフ化してみた ~その2~


はじめに

記事の概要

この記事では、前回に続いて、Jリーグの2019年の順位表を使って、matplotlibに加え、seabornの使い方を学びながら、サッカーにおいて順位と強く相関するものは何なのかを考察していきます。
自分の学習メモ代わりでもあるので、読みにくいかもしれませんがご容赦ください。

目的

・matplotlib,seabornの使い方に慣れる。
・DataFrameを扱えるようになる。
・サッカーの順位において、大事な要素を見つける。

コードと解説

前提

  • 開発環境
    • Anaconda
    • Python3
    • Juptyer-notebook

流れ

1. 前回の表(Jリーグのランキングと勝ち点等の表)を作成
2. とりあえず総得点と総失点の関係をグラフに
3. 順位とシュート数、得点の関係
4. 各要素の相関をヒートマップで見やすくする

コード

まず、前回の表を作成。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

url_ranking = 'https://data.j-league.or.jp/SFRT01/?search=search&yearId=2019&yearIdLabel=2019%E5%B9%B4&competitionId=460&competitionIdLabel=%E6%98%8E%E6%B2%BB%E5%AE%89%E7%94%B0%E7%94%9F%E5%91%BD%EF%BC%AA%EF%BC%91%E3%83%AA%E3%83%BC%E3%82%B0&competitionSectionId=0&competitionSectionIdLabel=%E6%9C%80%E6%96%B0%E7%AF%80&homeAwayFlg=3'
j_ranking = pd.read_html(url_ranking)
j_ranking = pd.DataFrame(j_ranking[0])
j_ranking = j_ranking.drop(['グラフ','試合','直近試合の勝敗','Unnamed: 12','Unnamed: 13'], axis=1) #不要なカラムの削除
j_ranking = j_ranking.rename(columns={"チーム":"チーム名"}) #もう一つの表と結合するためカラム名の変更

j_detail_ranking = 'https://data.j-league.or.jp/SFRT08/search?competitionYearEx=2019&competitionIdEx=1&selectedCompetitionName=%E6%98%8E%E6%B2%BB%E5%AE%89%E7%94%B0%E7%94%9F%E5%91%BD%EF%BC%AA%EF%BC%91%E3%83%AA%E3%83%BC%E3%82%B0&selectedCompetitionYear=2019%E5%B9%B4&competitionYear=2019&competitionId=1'
j_detail_ranking = pd.read_html(j_detail_ranking)
j_detail_ranking = pd.DataFrame(j_detail_ranking[0])
j_detail_ranking = j_detail_ranking.drop(18) #不要な行の削除
j_detail_ranking = j_detail_ranking.drop(['試合','試合時間','Unnamed: 19','退席','得点','失点','1試合平均得点','1試合平均失点'],axis=1) #不要なカラムの削除

j_all_ranking = j_ranking.merge(j_detail_ranking,on = 'チーム名')
j_all_ranking.head()

これで前回と同様の表が作成されます。
次に、総失点・総得点の関係を表にします。

import seaborn as sns

sns.set(font='Yu Gothic') #日本語表記に対応させます。
sns.jointplot(x='得点', y='失点', data=j_all_ranking);

たったこれだけで、以下の表ができます。
matplotlibと比べても少ないコードで楽ですね~
※図の上に、文字をプロットする方法はわかりませんでした。知っている方がいたらおしえてほしいです。

次に、順位と得点・シュート数の関係を図にしていきます。

f, ax = plt.subplots(figsize=(14, 8))

sns.set_color_codes("pastel")
sns.barplot(x="シュート", y="チーム名", data=j_all_ranking,
            label="シュート数", color="b")

sns.set_color_codes("muted")
sns.barplot(x="得点", y="チーム名", data=j_ranking,
            label="得点", color="b")

ax.legend(ncol=2, loc="lower right", frameon=True)
plt.xlabel('シュート数と得点数');

少ないコードで書けますし、横向きにできるのもいいですね。
表はこんな感じ。

この図を見ると、大分トリニータの特異性がはっきりと分かりますね。シュート数ではJ1最下位なのにこの順位にいるのは、かなり効率的に得点にしていることがうかがえます。

次に各要素の相関を見ていきたいと思います。
相関表の作成は前回もやったのですが、Seabornにはheatmapという便利な機能があるのでそれを使いたいと思います。


plt.figure(figsize=(20, 10))
#相関
pd.options.display.float_format = '{:.2f}'.format #有効数字を指定

j_rank_corr = j_all_ranking.corr()
sns.heatmap(j_rank_corr);


デフォルトの設定では少しわかりにくいので、設定をいじってみます。

plt.figure(figsize=(20, 10))
sns.heatmap(j_rank_corr,  cmap='coolwarm', annot=True);


この図を見れば何が強い相関を示しているか一目瞭然ですね。わかりやすい!
複数のカラム間の散布図を示すのも簡単です。
すべての要素を示すと重くなっていしまうので一部だけ…

sns.pairplot(j_all_ranking[['順位', '勝点', '勝', '得点','得失点差']]);

ここから得点と勝ち点の関係を詳しく抜き出してみます。

sns.regplot(data = j_all_ranking, x = '得点', y = '勝点');

デフォルトで回帰直線を示してくれるのもいいですね。

感想・反省

・とりあえず最低限の要素をいじった感じですが、seabornはコードが比較的わかりやすくていいですね。
・うまく扱うにはもう少し慣れが必要かな…

参考

Pythonを使って2019年度J1チームデータを可視化してみた
データサイエンスのためのPython入門講座全33回〜目次とまとめ〜