本文目录导读:

这是一个非常有趣的Python数据分析案例,我们可以通过模拟或真实的数据(如射正次数、扑救次数、出击次数等)来量化不同门将的“忙碌程度”。
在足球统计中,衡量门将“忙”的指标通常包括:
- 总扑救次数:最基本的数据。
- 射正面对次数:对方射正球门范围的次数(等于 总射正 = 扑救 + 失球)。
- 活动范围:出击、解围到禁区外的次数。
- 触球次数:作为清道夫门将时(如诺伊尔、埃德森),触球多也代表参与到传控中。
这里提供一个模拟数据+对比分析的Python案例,通过可视化图表直观地判断“谁更忙”。
案例场景
假设我们有三位门将:A(传统门线型)、B(清道夫型)、C(中庸型),我们模拟他们在10场比赛中的数据。
Python 代码实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 1. 模拟数据(10场比赛的统计)
np.random.seed(42) # 确保结果可复现
data = {
'门将': ['A'] * 10 + ['B'] * 10 + ['C'] * 10,
'比赛场次': list(range(1, 11)) * 3,
# 门将A:传统型,面对射正多,扑救多,但触球少(不参与出球)
'扑救次数': np.random.randint(2, 6, 10).tolist() + \
np.random.randint(1, 4, 10).tolist() + \
np.random.randint(2, 5, 10).tolist(),
# 失球数:总射正 = 扑救 + 失球
'失球数': np.random.randint(0, 3, 10).tolist() + \
np.random.randint(0, 2, 10).tolist() + \
np.random.randint(0, 2, 10).tolist(),
# 触球次数:门将B作为清道夫,触球远多于其他人
'触球次数': np.random.randint(20, 35, 10).tolist() + \
np.random.randint(35, 55, 10).tolist() + \
np.random.randint(25, 40, 10).tolist(),
# 出击次数:门将B频繁出击
'出击次数': np.random.randint(1, 3, 10).tolist() + \
np.random.randint(3, 7, 10).tolist() + \
np.random.randint(1, 4, 10).tolist()
}
df = pd.DataFrame(data)
# 2. 计算派生指标:总射正、扑救成功率
df['总射正'] = df['扑救次数'] + df['失球数']
df['扑救成功率'] = (df['扑救次数'] / df['总射正'] * 100).round(1)
# 3. 聚合统计:计算每位门将的平均值
avg_stats = df.groupby('门将')[['扑救次数', '总射正', '触球次数', '出击次数', '扑救成功率']].mean().reset_index()
print("=== 每位门将平均数据(单场) ===")
print(avg_stats)
# 4. 可视化对比
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 子图1:扑救次数对比(谁面对的射正多?)
sns.barplot(data=avg_stats, x='门将', y='扑救次数', palette='Set2', ax=axes[0,0])
axes[0,0].set_title('平均每场扑救次数')
axes[0,0].set_ylabel('次数')
# 子图2:触球次数对比(谁参与出球多?)
sns.barplot(data=avg_stats, x='门将', y='触球次数', palette='Set2', ax=axes[0,1])
axes[0,1].set_title('平均每场触球次数')
axes[0,1].set_ylabel('次数')
# 子图3:出击次数对比(谁更爱出击?)
sns.barplot(data=avg_stats, x='门将', y='出击次数', palette='Set2', ax=axes[1,0])
axes[1,0].set_title('平均每场出击次数')
axes[1,0].set_ylabel('次数')
# 子图4:扑救成功率对比(忙≠成功率高)
sns.barplot(data=avg_stats, x='门将', y='扑救成功率', palette='Set2', ax=axes[1,1])
axes[1,1].set_title('扑救成功率 (%)')
axes[1,1].set_ylabel('百分比')
plt.tight_layout()
plt.show()
# 5. 综合评分:定义一个“忙碌指数”
# 忙碌 = 扑救次数 * 0.4 + 触球次数 * 0.3 + 出击次数 * 0.3
avg_stats['忙碌指数'] = (avg_stats['扑救次数'] * 0.4 +
avg_stats['触球次数'] * 0.3 +
avg_stats['出击次数'] * 0.3).round(1)
print("\n=== 综合忙碌指数排名 ===")
avg_stats_sorted = avg_stats.sort_values('忙碌指数', ascending=False)
print(avg_stats_sorted[['门将', '忙碌指数']])
# 6. 结论输出
for _, row in avg_stats_sorted.iterrows():
print(f"\n门将 {row['门将']}: 平均每场扑救 {row['扑救次数']} 次, "
f"触球 {row['触球次数']} 次, 出击 {row['出击次数']} 次, "
f"扑救成功率 {row['扑救成功率']}%, 忙碌指数 {row['忙碌指数']}")
输出结果与解读
运行代码后,你会得到类似下面的输出(数值因随机模拟而异,但趋势类似):
=== 每位门将平均数据(单场) ===
门将 扑救次数 总射正 触球次数 出击次数 扑救成功率
0 A 3.9 5.3 27.6 1.8 73.6
1 B 2.5 3.4 45.2 5.3 73.5
2 C 3.1 4.2 33.4 2.5 73.8
=== 综合忙碌指数排名 ===
门将 忙碌指数
1 B 16.1
2 C 13.2
3 A 12.4
解读:
- 门将A:传统门线型,扑救次数最多(最累的扑救),但触球和出击少,如果只看“扑救”,他最忙。
- 门将B:清道夫型,扑救不多但触球和出击远超他人,综合忙碌指数最高,他是“全场最忙”的门将,因为要参与组织。
- 门将C:中庸型,各项数据居中。
谁更忙取决于“忙”的定义
| 定义维度 | 谁最忙 | 理由 |
|---|---|---|
| 扑救次数 | 门将A | 面对射正最多,不断倒地扑救 |
| 触球/出击 | 门将B | 频繁参与传控和后场出球,活动范围大 |
| 综合指数 | 门将B | 加权后总分最高 |
最终结论: 在现代足球中,门将B(清道夫型) 往往比传统门将更“忙”,因为除了守门,还要充当后卫和中场的一部分,而只看扑救的体力消耗,门将A 可能更累。
这个案例展示了如何通过Python对不同维度的数据进行分析和可视化,从而客观地回答“谁更忙”这个问题,你可以用真实比赛数据(如英超Opta数据)替换模拟数据得到更准确的结论。