Python案例:统计伤病停赛影响数据对比
下面用一个完整的案例,演示如何用 Python 分析球员伤病/停赛对球队战绩的影响。

场景说明
假设我们有一支足球队的数据,想要对比:
- 有主力球员伤病/停赛 时的比赛结果
- 阵容完整 时的比赛结果
通过胜率、场均积分、场均进球等指标做对比。
生成模拟数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
np.random.seed(42)
# 模拟 30 场比赛数据
n = 30
data = {
'比赛ID': range(1, n+1),
'对手强度': np.random.choice(['强', '中', '弱'], n),
'伤病停赛人数': np.random.choice([0, 1, 2, 3], n, p=[0.4, 0.3, 0.2, 0.1]),
'进球': np.random.randint(0, 4, n),
'失球': np.random.randint(0, 4, n),
}
df = pd.DataFrame(data)
# 计算比赛结果
def result(row):
if row['进球'] > row['失球']:
return '胜'
elif row['进球'] == row['失球']:
return '平'
else:
return '负'
df['结果'] = df.apply(result, axis=1)
# 计算积分
df['积分'] = df['结果'].map({'胜': 3, '平': 1, '负': 0})
# 标记是否受伤病影响
df['伤病影响'] = df['伤病停赛人数'].apply(lambda x: '有影响' if x > 0 else '无影响')
print(df.head(10))
核心统计对比
# 分组统计
summary = df.groupby('伤病影响').agg(
场次=('比赛ID', 'count'),
胜场=('结果', lambda x: (x == '胜').sum()),
平场=('结果', lambda x: (x == '平').sum()),
负场=('结果', lambda x: (x == '负').sum()),
总积分=('积分', 'sum'),
总进球=('进球', 'sum'),
总失球=('失球', 'sum'),
).reset_index()
# 计算衍生指标
summary['胜率'] = (summary['胜场'] / summary['场次'] * 100).round(1)
summary['场均积分'] = (summary['总积分'] / summary['场次']).round(2)
summary['场均进球'] = (summary['总进球'] / summary['场次']).round(2)
summary['场均失球'] = (summary['总失球'] / summary['场次']).round(2)
print("\n===== 伤病影响对比表 =====")
print(summary[['伤病影响', '场次', '胜率', '场均积分', '场均进球', '场均失球']])
输出示例:
===== 伤病影响对比表 =====
伤病影响 场次 胜率 场均积分 场均进球 场均失球
0 无影响 13 53.8 1.77 1.77 1.38
1 有影响 17 29.4 1.12 1.18 1.88
按伤病人数细化分析
# 按具体伤病人数分组
detail = df.groupby('伤病停赛人数').agg(
场次=('比赛ID', 'count'),
胜率=('结果', lambda x: (x == '胜').mean() * 100),
场均积分=('积分', 'mean'),
场均进球=('进球', 'mean'),
场均失球=('失球', 'mean'),
).round(2).reset_index()
print("\n===== 按伤病人数细分 =====")
print(detail)
可视化对比
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# 图1:场均积分对比
axes[0].bar(summary['伤病影响'], summary['场均积分'], color=['#4CAF50', '#F44336'])
axes[0].set_title('场均积分对比')
axes[0].set_ylabel('积分')
for i, v in enumerate(summary['场均积分']):
axes[0].text(i, v + 0.05, str(v), ha='center')
# 图2:胜率对比
axes[1].bar(summary['伤病影响'], summary['胜率'], color=['#2196F3', '#FF9800'])
axes[1].set_title('胜率对比(%)')
axes[1].set_ylabel('胜率 %')
for i, v in enumerate(summary['胜率']):
axes[1].text(i, v + 1, f'{v}%', ha='center')
# 图3:按伤病人数胜率趋势
axes[2].plot(detail['伤病停赛人数'], detail['胜率'], marker='o', color='#9C27B0')
axes[2].set_title('胜率随伤病人数变化')
axes[2].set_xlabel('伤病/停赛人数')
axes[2].set_ylabel('胜率 %')
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('injury_impact.png', dpi=100)
plt.show()
进阶:卡方检验(判断差异是否显著)
from scipy.stats import chi2_contingency
# 构建列联表
contingency = pd.crosstab(df['伤病影响'], df['结果'])
print("\n列联表:")
print(contingency)
chi2, p, dof, expected = chi2_contingency(contingency)
print(f"\n卡方值: {chi2:.3f}, p值: {p:.4f}")
if p < 0.05:
print("→ 伤病/停赛对比赛结果有显著影响")
else:
print("→ 数据不足以证明伤病对结果有显著影响")
关键结论输出
no_injury = summary[summary['伤病影响'] == '无影响'].iloc[0]
has_injury = summary[summary['伤病影响'] == '有影响'].iloc[0]
print("\n===== 分析结论 =====")
print(f"1. 无伤病时场均积分 {no_injury['场均积分']},"
f"有伤病时 {has_injury['场均积分']},"
f"下降 {no_injury['场均积分'] - has_injury['场均积分']:.2f} 分")
print(f"2. 胜率从 {no_injury['胜率']}% 降至 {has_injury['胜率']}%")
print(f"3. 场均失球从 {no_injury['场均失球']} 升至 {has_injury['场均失球']}")
可扩展方向
| 方向 | 说明 |
|---|---|
| 真实数据接入 | 用 requests 爬取虎扑、懂球帝等数据 |
| 球员级分析 | 分析具体某位核心球员缺阵的影响 |
| 位置分组 | 按后卫/中场/前锋缺阵分别统计 |
| 时间序列 | 用 statsmodels 做 ARIMA 预测 |
| 机器学习 | 用随机森林评估伤病对未来比赛的影响权重 |
核心思路:把"是否受伤病影响"作为分组维度,对比关键战绩指标(胜率、积分、进失球),再结合统计检验判断显著性。
需要我针对某支具体球队/某个联赛或球员级伤病分析进一步展开吗?