🏆 はじめに
今年のパリーグはソフトバンクホークスが独走して優勝しました。
2年連続最下位だった日本ハムファイターズは2位に躍進しました。
最下位は山賊打線が解体された西武ライオンズでした。
その他、3位は千葉ロッテマリーンズ、4位は楽天イーグルス、5位はオリックスバファローズでした。
ここで今季の順位表をスポナビさんから拝借させていただきます。
https://baseball.yahoo.co.jp/npb/standings/detail/2 から引用
順位 | チーム名 | 勝利 | 敗戦 | 引分 | 勝率 | 勝差 | 得点 | 失点 | 本塁打 | 盗塁 | 打率 | 防御率 | 失策 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | ソフトバンク | 91 | 49 | 3 | .650 | - | 607 | 390 | 114 | 89 | .259 | 2.53 | 53 |
2 | 日本ハム | 75 | 60 | 8 | .556 | 13.5 | 532 | 485 | 111 | 91 | .245 | 2.94 | 75 |
3 | ロッテ | 71 | 66 | 6 | .518 | 5 | 493 | 495 | 75 | 64 | .248 | 3.17 | 71 |
4 | 楽天 | 67 | 72 | 4 | .482 | 5 | 492 | 579 | 72 | 90 | .242 | 3.73 | 64 |
5 | オリックス | 63 | 77 | 3 | .450 | 4.5 | 402 | 448 | 71 | 61 | .238 | 2.82 | 78 |
6 | 西武 | 49 | 91 | 3 | .350 | 14 | 350 | 485 | 60 | 83 | .212 | 3.02 | 72 |
この順位表を基にPythonでデータ分析をしていきます
📊 分析するテーマ
- 得点と失点の関係
- 本塁打と得点の関係
- 盗塁と得点の関係
- 打率と得点の関係
- 防御率と勝利数の関係
- 防御率と失策の関係
🛠️ 環境構築
pip install pandas numpy seaborn matplotlib japanize-matplotlib
🧑💻 コード
必要なライブラリを設定します
順位表はCSV形式で保存したものを読み込んでDataFrame型にします
import pandas as pd
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
import japanize_matplotlib
# セリーグの順位表を読み込む
df = pd.read_csv('baseball/data/order.csv')
# 凡例のチームカラーの設定
team_colors = {
'オリックス': 'navy',
'ソフトバンク': 'yellow',
'楽天': 'red',
'ロッテ': 'black',
'西武': 'blue',
'日本ハム': 'cyan'
}
得点と失点のグラフ
# 得点と失点の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='失点', y='得点', hue='チーム名', palette=team_colors, s=100)
plt.title('得点と失点の関係')
plt.xlabel('失点')
plt.ylabel('得点')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['失点'], row['得点'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 得点と失点の平均値を示す線を追加
plt.axvline(df['失点'].mean(), color='red', linestyle='--', label='失点の平均')
plt.axhline(df['得点'].mean(), color='blue', linestyle='--', label='得点の平均')
plt.show()
縦軸に得点数、横軸に失点数のグラフです。
得点と失点の平均線をそれぞれ青、赤色で示しています。
各ポイントの左上の数字は順位を表しています。
ソフトバンク (1位)
- 得点が600以上、失点が400未満と、他のチームに比べて圧倒的に得点力が高く、失点も少ないです
- この位置は、攻撃面と守備面の両方が非常に優れており、リーグでの圧倒的な優位性を示しています。リーグ優勝も納得できるデータです
日本ハム (2位)
- 得点と失点のバランスが比較的良く、得点532に対して失点485と、失点が得点を下回っており、勝率の高さを反映しています
- 勝率が高い理由は、失点を最小限に抑えつつ、得点力も維持している点にあります
ロッテ (3位)
- 得点がほぼ失点と同じ493に対して495となっており、拮抗しています
- これは、接戦が多く、勝ち負けが安定していない状況を示唆しており、順位が中位であることに納得できる理由です
楽天 (4位)
- 得点が492であるのに対して失点が579と、失点が非常に多いです
- このデータは、攻撃力はあるものの、守備や投手陣の弱さが試合に影響を与えていることを示しており、順位が低い理由もここにあります
オリックス (5位)
- 得点が402、失点が448と、得点力が非常に低く、失点も比較的多いです
- 攻撃面での不振が大きな課題であり、これがチームの低迷を招いていることが読み取れます
西武 (6位)
- 得点が350、失点が485と、攻撃面でも守備面でも苦戦しています
- チーム全体の力不足が順位にも反映されており、攻撃も守備も強化が必要であることが明らかです
リーグ全体の傾向
平均よりも得点の多いチームはソフトバンクから楽天までの順位が1位から4位までを占め、下位のオリックスと西武が平均を押し下げるほどの成績でした。
失点面では、ソフトバンクとオリックスが平均よりも低い失点数を記録し、ディフェンス面の高さを表しています。
本塁打と得点の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='本塁打', y='得点', hue='チーム名', palette=team_colors, s=100)
plt.title('本塁打と得点の関係')
plt.xlabel('本塁打')
plt.ylabel('得点')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['本塁打'], row['得点'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 本塁打と得点の平均値を示す線を追加
plt.axvline(df['本塁打'].mean(), color='red', linestyle='--', label='本塁打の平均')
plt.axhline(df['得点'].mean(), color='blue', linestyle='--', label='得点の平均')
# 相関係数
correlation_coefficient = np.corrcoef(df['本塁打'], df['得点'])[0, 1]
plt.text(0.1, 0.9, f'r: {correlation_coefficient:.2f}', transform=plt.gca().transAxes)
# 回帰直線
slope, intercept = np.polyfit(df['本塁打'], df['得点'], 1)
x = np.linspace(min(df['本塁打']), max(df['本塁打']), 100)
y = slope * x + intercept
plt.plot(x, y, color='black', label=f'回帰直線: y = {slope:.2f}x + {intercept:.2f}', alpha=0.2)
plt.show()
本塁打数が多いチームほど得点が多くなる傾向があり、特にソフトバンクと日本ハムはその代表例です。
一方、本塁打数が少ないオリックスや西武は、得点力が低く、攻撃面での強化が必要であることが読み取れます。
ソフトバンク (1位)
- ソフトバンクは、他のチームと比べて圧倒的に多くの本塁打を打っており、得点も最多です。このデータは、攻撃力の強さを本塁打数が裏付けていることを示しています
日本ハム (2位)
- 日本ハムはソフトバンクに次いで本塁打数が多く、得点も高いです。本塁打が得点に大きく寄与していることが伺えます
ロッテ (3位) と楽天 (4位)
- ロッテと楽天は、本塁打数が中間に位置し、得点もそれに応じた範囲に収まっています。これらのチームも、本塁打がある程度得点に影響を与えていると考えられますが、他の要素(例えばヒット数や盗塁など)が得点に与える影響も無視できません
オリックス (5位)
- オリックスは本塁打数が少なく、それに比例して得点も低いです。これは、攻撃力の弱さを反映しており、本塁打が少ないために得点力も低いことが示されています
西武 (6位)
- 西武は最も本塁打が少なく、得点も最低です。本塁打が少ないことがチーム全体の得点力の低さに繋がっていることが明確です
リーグ全体の傾向
グラフ上に表示された相関係数「r = 0.87」から、本塁打数と得点には強い正の相関があることが分かります。一般的に、相関係数が0.8以上であれば強い相関があるとされます。したがって、本塁打が多いチームほど得点が多くなる傾向が強いことが読み取れます。
特にソフトバンクと日本ハムは、本塁打数が多く、それに比例して得点も高くなっています。
盗塁と得点の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='盗塁', y='得点', hue='チーム名', palette=team_colors, s=100)
plt.title('盗塁と得点の関係')
plt.xlabel('盗塁')
plt.ylabel('得点')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['盗塁'], row['得点'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 得点と失点の平均値を示す線を追加
plt.axvline(df['盗塁'].mean(), color='red', linestyle='--', label='盗塁の平均')
plt.axhline(df['得点'].mean(), color='blue', linestyle='--', label='得点の平均')
# 相関係数
correlation_coefficient = np.corrcoef(df['盗塁'], df['得点'])[0, 1]
plt.text(0.1, 0.9, f'r2: {correlation_coefficient:.2f}', transform=plt.gca().transAxes)
# 回帰直線
slope, intercept = np.polyfit(df['盗塁'], df['得点'], 1)
x = np.linspace(min(df['盗塁']), max(df['盗塁']), 100)
y = slope * x + intercept
plt.plot(x, y, color='black', label=f'回帰直線: y = {slope:.2f}x + {intercept:.2f}', alpha=0.2)
plt.show()
図の右上に位置するチーム(ソフトバンク、日本ハム)が上位を占めており、攻撃的な戦略が成功している傾向が見られます。
ただし、盗塁数の多さだけでは必ずしも得点に直結していないことも明確です。
ソフトバンク(1位)
- 盗塁数89と得点607はともに高く、攻撃力の高さが際立っています
- 盗塁が効果的に得点に結びついているチームです
日本ハム(2位)
- 盗塁数91がリーグ最多で、得点532と上位に位置しています
- 積極的な走塁が得点に貢献している可能性が高いです
ロッテ(3位)
- 盗塁数64でリーグ内では少なめですが、得点は493とそこそこの数値を維持しています
- 盗塁以外の攻撃戦略が得点に寄与していると考えられます
楽天(4位)
- 盗塁数90は高いものの、得点は492で中位に留まっています
- 盗塁だけでは得点を大幅に伸ばせていない様子が見て取れます
オリックス(5位)
- 盗塁数61と少なめで、得点も402と低いです
- 守備面や打撃面での戦略が盗塁の少なさを補うことができていない可能性があります
西武(6位)
- 盗塁数83と健闘しているものの、得点は350と最下位です
- 盗塁が得点に結びついていない典型的な例です
リーグ全体の傾向
グラフ左上に表示されている決定係数(r2)が0.43と、それほど強い相関関係は見られません。これは得点力と盗塁数が必ずしも直接的な関係にないことを示唆しています。
オリックスと西武は盗塁数は比較的近い(61と83)にも関わらず、得点差(402と350)があります。これは盗塁以外の要素(打率や長打力など)が得点に大きく影響していることを示唆しています。
打率と得点の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='打率', y='得点', hue='チーム名', palette=team_colors, s=100)
plt.title('打率と得点の関係')
plt.xlabel('打率')
plt.ylabel('得点')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['打率'], row['得点'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 得点と失点の平均値を示す線を追加
plt.axvline(df['打率'].mean(), color='red', linestyle='--', label='打率の平均')
plt.axhline(df['得点'].mean(), color='blue', linestyle='--', label='得点の平均')
# 相関係数
correlation_coefficient = np.corrcoef(df['打率'], df['得点'])[0, 1]
plt.text(0.1, 0.9, f'r2: {correlation_coefficient:.2f}', transform=plt.gca().transAxes)
# 回帰直線
slope, intercept = np.polyfit(df['打率'], df['得点'], 1)
x = np.linspace(min(df['打率']), max(df['打率']), 100)
y = slope * x + intercept
plt.plot(x, y, color='black', label=f'回帰直線: y = {slope:.2f}x + {intercept:.2f}', alpha=0.2)
plt.show()
このグラフは、2024年のパ・リーグにおける打率と得点の関係を示しています。
決定係数 (r² = 0.91) からわかるように、打率と得点には非常に強い正の相関があり、打率が高いチームほど得点が多くなる傾向が顕著です。
打率が攻撃力を大きく左右する重要な要素であることが示されています。
ソフトバンク(1位)
- 打率0.259とリーグで最も高く、得点も607と他チームを大きく上回っています
- 打率が高いため、安打が多く得点力も高い。打撃の強さがそのまま得点力の高さに繋がっています
日本ハム(2位)
- 打率0.245でリーグ内では中位ですが、得点532と上位に位置しています
- 打率以外にも、効率的な得点の取り方や長打力が高得点に寄与している可能性があります
ロッテ(3位)
- 打率0.248で、日本ハムとほぼ同じですが、得点は493と若干低いです
- 打率の割には得点が伸びていないため、チャンスでの得点力や攻撃の効率性に改善の余地がありそうです
楽天(4位)
- 打率0.242で得点492と、打率と得点がほぼ比例しています
- 打撃力をさらに向上させることが得点力の増加に直結する可能性があります
オリックス(5位)
- 打率0.238と低めで、得点も402と下位に留まっています
- 打率が低いことがそのまま得点不足に繋がっており、打撃力の強化が必要です
西武(6位)
- 打率0.212でリーグ最低、得点も350と最下位です
- 打率の低さが直接的に得点力の低さに繋がっており、打撃力の向上が大きな課題です
リーグ全体の傾向
このグラフから、打率と得点には非常に強い相関があることが確認できます (r² = 0.91)。
打率が高いチームは得点も多く、打率の向上が得点力の向上に直結する傾向が顕著です。
各チームは打撃力を強化することで、得点力をさらに伸ばすことが可能であることが示唆されます。
防御率と勝利数の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='防御率', y='勝利', hue='チーム名', palette=team_colors, s=100)
plt.title('防御率と勝利数の関係')
plt.xlabel('防御率')
plt.ylabel('勝利数')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['防御率'], row['勝利'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 得点と失点の平均値を示す線を追加
plt.axvline(df['防御率'].mean(), color='red', linestyle='--', label='防御率の平均')
plt.axhline(df['勝利'].mean(), color='blue', linestyle='--', label='勝利数の平均')
# 相関係数
correlation_coefficient = np.corrcoef(df['防御率'], df['勝利'])[0, 1]
plt.text(0.1, 0.9, f'r2: {correlation_coefficient:.2f}', transform=plt.gca().transAxes)
# 回帰直線
slope, intercept = np.polyfit(df['防御率'], df['勝利'], 1)
x = np.linspace(min(df['防御率']), max(df['防御率']), 100)
y = slope * x + intercept
plt.plot(x, y, color='black', label=f'回帰直線: y = {slope:.2f}x + {intercept:.2f}', alpha=0.2)
plt.show()
決定係数 (r² = -0.40) が示す通り、防御率と勝利数にはわずかに負の相関が見られますが、相関は強くなく、単に防御率が低いからといって勝利数が多いわけではないことが示唆されています。
ソフトバンク(1位)
- 防御率2.53と非常に低く、勝利数は91でリーグ最多です
- 投手陣が安定しており、強力な守備力が勝利に貢献していると考えられます
日本ハム(2位)
- 防御率2.94と優秀で、勝利数は75と上位に位置しています
- 防御率の安定が勝利数にも良い影響を与えている可能性が高いです
ロッテ(3位)
- 防御率3.17で、勝利数は71です。防御率がリーグ中位ながらも、勝利数も中程度に留まっています
- チーム全体のバランスが取れているため、防御率に見合った勝利数といえます
楽天(4位)
- 防御率3.73と高めで、勝利数は67と中位です
- 防御率がやや高いため、投手陣に改善の余地がありそうです
オリックス(5位)
- 防御率2.82と比較的良いにも関わらず、勝利数は63で下位に位置しています
- 投手陣は安定しているものの、得点力不足や攻撃面での課題が勝利数に影響している可能性があります
西武(6位)
- 防御率3.02で、勝利数は49と最下位です
- 防御率はリーグ平均程度ですが、得点力不足や守備面での課題が勝利数の低さに影響していると考えられます
リーグ全体の傾向
グラフから、防御率と勝利数にはわずかな負の相関があることが確認できます (r² = -0.40)。防御率が低いほど勝利数が多い傾向は見られるものの、防御率以外の要因(例えば得点力)が勝利数に大きな影響を与える可能性が高いです。
防御率と失策の関係
plt.figure(figsize=(10, 5))
sns.scatterplot(data=df, x='失策', y='防御率', hue='チーム名', palette=team_colors, s=100)
plt.title('防御率と失策の関係')
plt.xlabel('失策')
plt.ylabel('防御率')
plt.grid(True)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
for i, row in df.iterrows():
plt.text(
row['失策'], row['防御率'], str(row['順位']), color='black',
fontsize=10, ha='right', va='bottom'
)
# 得点と失点の平均値を示す線を追加
plt.axvline(df['失策'].mean(), color='red', linestyle='--', label='失策の平均')
plt.axhline(df['防御率'].mean(), color='blue', linestyle='--', label='防御率の平均')
# 相関係数
correlation_coefficient = np.corrcoef(df['防御率'], df['失策'])[0, 1]
plt.text(0.1, 0.9, f'r2: {correlation_coefficient:.2f}', transform=plt.gca().transAxes)
# 回帰直線
slope, intercept = np.polyfit(df['失策'], df['防御率'], 1)
x = np.linspace(min(df['失策']), max(df['失策']), 100)
y = slope * x + intercept
plt.plot(x, y, color='black', label=f'回帰直線: y = {slope:.2f}x + {intercept:.2f}', alpha=0.2)
plt.show()
防御率と失策の関係
このグラフは、2024年のパ・リーグにおける防御率と失策の関係を示しています。決定係数 (r² = 0.13) が示す通り、防御率と失策数にはほとんど相関がなく、失策数が少ないからといって防御率が必ずしも低くなるわけではないことがわかります。
ソフトバンク(1位)
- 防御率2.53と非常に低く、失策数も53と最も少ない
- 守備が安定しており、失策の少なさが防御率の良さに貢献していると考えられます
日本ハム(2位)
- 防御率2.94でリーグ上位、失策数は75で下位
- 防御率の良さから、失策の影響を最小限に抑えていると考えられます
ロッテ(3位)
- 防御率3.17、失策数は71で中位
- 失策がある程度あるものの、チーム全体の守備力で防御率を安定させている可能性があります
楽天(4位)
- 防御率3.73と高めで、失策数は64でリーグ中位
- 失策数は多くないものの、防御率が高いため投手陣の改善が課題です
オリックス(5位)
- 防御率2.82で優秀ですが、失策数は78でリーグ最多
- 守備に課題があるものの、防御率が良いため投手力でカバーしている様子が伺えます
西武(6位)
- 防御率3.02で平均的、失策数は72で中位
- 失策数が多いため、守備面での改善が防御率の向上に貢献する可能性があります
リーグ全体の傾向
このグラフから、防御率と失策数にはわずかな正の相関がありますが (r² = 0.13)、影響は小さいです。失策が少ないチームほど防御率が低い傾向はあるものの、防御率の良し悪しは主に投手力や守備全体の安定性に依存していることが示唆されます。
おわりに
エスコン開業2年目を本拠地にしている日ハムは失策がリーグ2位で連続のリーグ下位に位置しました。秋季キャンプもエスコンで実施するようで、失策が毎年少なくなっていくとおもしろです。ただ、失策が多くてもリーグ順位が2位だったので悲観することはなさそうです。
また、1つの項目ごとに対象のデータで分析結果をまとめているので他の項目の観点は考慮していないです。