今回は、プログラミング言語であるPythonを用いて、B.LEAGUE B2に所属している 「群馬 CRANE THUNDERS」のスタッツをデータ分析してみました。
本ブログでは主に、チームの特徴や勝敗のポイントなどを記載していきます。
▼ Contents
1. 2020年度B2リーグ順位表
まず、レギュラーシーズンのB2順位表を確認します。

群馬 CRANE THUNDERSは全体第1位となります。勝率91.2%はすごいとしか言いようがないですね。。。
この強さはどこにあるのか、スタッツから分析していきます。
2. 平均スタッツ
群馬 CRANE THUNDERSのスタッツを確認していきます。以下のグラフはB2リーグの平均値を50とする偏差値方式で表示しています。具体的な数値や、平均値のランクはその都度記載していきます。
「Team」の項目は、本記事の対象チーム(今回は群馬 CRANE THUNDERS)の値、「OppTeam」は本記事対象チームの対戦相手の値となります。「OppTeam」の値は小さい方が本記事の対象チームにとって値が高いということになります。
まずは基本スタッツを確認します。



特筆すべきは、PTS(得点)、2PM(2Pシュート成功数)、AST(アシスト)がB2全体で1位となっています。また、平均失点も76.3点のリーグ2位、Opp-TOVも多く、Opp-DRBやOpp-TRBもB2リーグ1位で少ないです。
4 Factorも確認しておきます。



4-Factorを見ても、B2リーグ1位の貫禄が出ています。特に得点効率が偏差値69.3とほぼ上位5%と素晴らしいですね。一方、Opp-eFG%やOpp-TOV%も少なくB2リーグ2位となっています。
3. 得点関連
得点の取得割合を見ていきます。まずはシュートアテンプト数です。



群馬 CRANE THUNDERSは、2Pアテンプト数がリーグ2位の平均45.2回です。また、2Pの中でもIPA(インサイドペイント)でのシュートアテンプト数が平均34.1回でリーグ4位です。
一方、Opp-3PAやOpp-OP(アウトサイドペイント)はB2リーグ平均以下となっており、対戦相手のシュートをなるべく外側から打たせる守備をしていることが伺えます。
また、得点ケースを見てみましょう。



得点ケースでは、全得点に対する2Pの割合(2P/PTS)がBリーグ4位、特に全得点に対するFBP(速攻)の割合(FBP%)は、偏差値71.4のB2リーグ1位です。
対する対戦相手は、3P/PTSが高いことから、3Pでの得点が多くなる傾向があるようです。群馬のインサイドの強さが垣間見えます。
4. アシスト関連



群馬はアシストもB2リーグで1位ですが、2P%、3P%、FG%も1位となっており、高い得点効率となっています。
また、対戦相手のFG%も大きく抑えてB2リーグ2位ですので、隙が殆どありません。
5. リバウンド関連



リバウンドスタッツも総じて素晴らしく、対戦相手のDRBはB2リーグ最小です。これは群馬の得点効率も影響していると考えられます。
6. 勝敗時のスタッツ比較
ここまでスタッツが優秀だと逆に弱点を発見したくなります(笑)。とはいえ弱点を発見するのは大変そうですので、勝敗別にスタッツを見直してみます。ちなみに群馬はRSは5敗しかしていません。(Homeは全勝。。。すごい。)
特に注目すべきスタッツは以下です。
6-1. 敗戦時は3P、OPアテンプト数が増え、FBP%が減少する


群馬は敗戦時は3PやOPのアテンプト数が上昇しており、強みであるIPでの得点(PfT%やFBP%)が大きく減少しています。
6-2. 敗戦時はリバンドが取れていない

勝利時は圧倒的にリバウンドが取れていますが、敗戦時はなかなかリバウンドが取れなかったようです。一方、対戦相手のリバウンド取得数が向上しています。
7. 考察
B2リーグ首位であり、RS勝率も9割超えの群馬CRANE THUNDERS。間違いなくB2リーグ優勝筆頭候補です。
ほとんど隙がありませんが、できる限りゴールから遠い箇所からのシュートアテンプト数を増やさせ、DRBをしっかり取れれば、勝ち筋が見えてくるかもしれません。

でも、群馬は平均3P%は35.9%のB2リーグ1位、、、強い(確信)

GO!CRANE THUNDERS!
8. サンプルコード
以下は、Pythonでのレーダーチャートのコード例です。
df_teamは本記事対象チームの2020年度平均スタッツ、df_oppteamは対戦相手の2020年度平均スタッツとなります。
まず、polar_list関数で、表示したデータを抽出して辞書化します。その後、plot_polar関数でレーダーチャートを表示します。
def poloar_list(df_team, df_oppteam, b_team):
polar_list1 = ['PTS', '3PM', '2PM', 'FTM', 'AST', 'TOV', 'STL', 'ORB', 'TRB', 'DRB', 'BLK']
polar_list2 = ['eFG%', 'ORB%', 'TOV%', 'FT/FGA']
polar_list3 = ['FGA', '3PA', '3PA%', 'OPA', 'OPA%', '2PA', '2PA%', 'IPA', 'IPA%', 'FTA']
polar_list4 = ['PTS', '3P/PTS', '2P/PTS', 'PfT%', 'PitP%', 'SCP%', 'FBP%', 'FT/PTS']
polar_list5 = ['AST', 'TOV', 'AST/TOV', 'STL', '3P%', '2P%', 'FG%']
polar_list6 = ['ORB', 'ORB%', 'Opp_DRB', 'DRB', 'DRB%', 'Opp_ORB', 'TRB', 'TRB%', 'Opp_TRB']
df_team = df_team.loc["{}".format(b_team)]
df_oppteam = df_oppteam.loc["{}".format(b_team)]
df_polar_team = df_team[polar_list1]
df_polar_oppteam = df_oppteam[polar_list1]
df_polar_team_4factor = df_team[polar_list2]
df_polar_oppteam_4factor = df_oppteam[polar_list2]
df_polar_team_attempt = df_team[polar_list3]
df_polar_oppteam_attempt = df_oppteam[polar_list3]
df_polar_team_point = df_team[polar_list4]
df_polar_oppteam_point = df_oppteam[polar_list4]
df_polar_team_ast = df_team[polar_list5]
df_polar_oppteam_ast = df_oppteam[polar_list5]
df_polar_team_rb = df_team[polar_list6]
df_polar_oppteam_rb = df_oppteam[polar_list6]
df_dict = {
0: ["Team", df_polar_team], 1: ["Oppteam", df_polar_oppteam],
2: ["Team_4factor", df_polar_team_4factor], 3: ["Oppteam_4factor", df_polar_oppteam_4factor],
4: ["Team_Attempt", df_polar_team_attempt], 5: ["Oppteam_Attempt", df_polar_oppteam_attempt],
6: ["Team_point", df_polar_team_point], 7: ["Oppteam_point", df_polar_oppteam_point],
8: ["Team_AST", df_polar_team_ast], 9: ["Oppteam_AST", df_polar_oppteam_ast],
10: ["Team_RB", df_polar_team_rb], 11: ["Oppteam_RB ", df_polar_oppteam_rb]
}
return df_dict
def plot_polar(df_dict, b_team, N=2):
sns.set(font_scale=1.0)
fig, ax = plt.subplots(6, N, figsize=(12, 48), subplot_kw={'projection': 'polar'})
for i, df in df_dict.items():
x, y = divmod(i, N)
labels = df[1].index
values = list(df[1])
angles = np.linspace(0, 2 * np.pi, len(labels) + 1, endpoint=True)
values = np.concatenate((values, [values[0]]))
ax[x, y].plot(angles, values, 'o-', color="blue", label="Overall: {}".format(round(df[1].mean(), 1)))
ax[x, y].fill(angles, values, alpha=0.25, color="blue")
ax[x, y].set_rlim(20, 80)
ax[x, y].set_thetalim([-np.pi, np.pi])
ax[x, y].set_thetagrids(angles[:-1] * 180 / np.pi, labels, fontsize=15)
ax[x, y].set_theta_zero_location('N')
ind = 2
gridlines = ax[x, y].yaxis.get_gridlines()
gridlines[2].set_color("black")
gridlines[ind].set_linewidth(1)
gridlines[ind].set_linestyle("--")
ax[x, y].set_title("{0}: {1} ".format(df[0], b_team), fontsize=15)
ax[x, y].legend(bbox_to_anchor=(0.5, -0.18), loc= 'lower center')
plt.tight_layout()
plt.show()
こちらの記事を参照させていただきました↓
公式のサンプルはうまくプロットできないし、コードが長くて死ぬ。
シンプルにレーダーチャートを描きたいだけなのに…。
Matplotlibでレーダーチャートを描く(16行)

以下の記事も書いています。よかったらご覧ください。

Twitterもやってまーす。
圧倒的ですね!