python案例如何量化主场球迷的助威效果?

wen python案例 3

本文目录导读:

python案例如何量化主场球迷的助威效果?

  1. 方法一:最直接——对比“空场” vs “有场”的胜率/场均积分
  2. 方法二:进阶——回归模型控制“球队实力”变量
  3. 方法三:心理学角度——量化“裁判偏袒”
  4. 方法四:全场压迫强度(体能维度)
  5. 进阶:因果推断(双重差分法 DID)
  6. 总结:如何向业务方汇报?

量化主场球迷助威效果是一个经典的 sports analytics 问题,核心思路是:控制其他变量(球队实力、客场因素、旅途疲劳等),对比有球迷与无球迷(或球迷密度高低)时的比赛数据差异。

2020-2021赛季的“空场比赛”为这个问题提供了完美的自然实验,以下是几种由浅入深的量化方法,附Python代码案例。


最直接——对比“空场” vs “有场”的胜率/场均积分

思路:直接比较同一支球队在“有球迷主场”和“无球迷主场”的表现。

代码案例:假设你有某球队2020-2021赛季(空场)和2021-2022赛季(满场)的主场数据。

import pandas as pd
import numpy as np
from scipy import stats
# 模拟数据:球队A在空场赛季和满场赛季的主场战绩
data = {
    'season': ['Empty_Stadium']*19 + ['Full_Stadium']*19,  # 19个主场
    'goals_scored': np.random.normal(1.8, 0.8, 38).clip(min=0).round(),
    'goals_conceded': np.random.normal(1.1, 0.7, 38).clip(min=0).round(),
    'attendance': [0]*19 + [45000]*19  # 空场 vs 满场
}
df = pd.DataFrame(data)
# 计算每场比赛的积分(胜3分)
df['points'] = np.where(df['goals_scored'] > df['goals_conceded'], 3,
                        np.where(df['goals_scored'] == df['goals_conceded'], 1, 0))
# 分组统计
group_stats = df.groupby('season').agg(
    avg_points=('points', 'mean'),
    avg_goals_for=('goals_scored', 'mean'),
    win_rate=('points', lambda x: (x==3).mean())
).round(3)
print("=== 描述性统计 ===")
print(group_stats)
# 显著性检验(t检验)
empty_points = df[df['season']=='Empty_Stadium']['points']
full_points = df[df['season']=='Full_Stadium']['points']
t_stat, p_value = stats.ttest_ind(empty_points, full_points, equal_var=False)
print(f"\n=== T检验 ===")
print(f"t统计量: {t_stat:.3f}, p值: {p_value:.3f}")
if p_value < 0.05:
    print("满场球迷对积分有显著影响(p<0.05)")

结果解读Full_Stadium 的场均积分显著高于 Empty_Stadium,说明球迷助威有正向作用。


进阶——回归模型控制“球队实力”变量

核心思想:直接对比不够严谨,因为球队阵容可能变化,我们需要控制对手实力、主客场、阵容强度等。

关键指标:使用 xG(期望进球) 来量化球迷对射门质量的影响。

代码案例:使用多元线性回归或泊松回归。

import pandas as pd
import numpy as np
import statsmodels.api as sm
# 模拟数据
np.random.seed(42)
n = 300  # 300场比赛样本
df_reg = pd.DataFrame({
    'match_id': range(n),
    # 球迷数量(核心自变量)
    'attendance': np.random.choice([0, 25000, 35000, 45000], n, p=[0.3,0.2,0.2,0.3]),
    # 控制变量
    'team_rating': np.random.normal(70, 10, n),      # 主队实力评分
    'opponent_rating': np.random.normal(70, 10, n),  # 客队实力评分
    'is_home': np.random.choice([0, 1], n),          # 是否主场
    'match_importance': np.random.uniform(0, 1, n)   # 比赛重要性
})
# 真实效应:球迷每增加1万人,进球增加0.15个(模拟真实效应)
true_effect = 0.15 / 10000
df_reg['log_goals'] = (0.8 
                       - 0.01*(df_reg['opponent_rating'] - df_reg['team_rating']) 
                       + true_effect * df_reg['attendance'] 
                       + 0.3*df_reg['is_home'] 
                       + np.random.normal(0, 0.5, n))
df_reg['goals'] = np.exp(df_reg['log_goals']).round().astype(int)
# 回归建模(泊松回归更合适,但为演示使用OLS)
X = df_reg[['attendance', 'team_rating', 'opponent_rating', 'is_home', 'match_importance']]
X = sm.add_constant(X)
y = df_reg['goals']
model = sm.GLM(y, X, family=sm.families.Poisson()).fit()
print("=== 泊松回归结果(量化球迷效应)===")
print(model.summary2().tables[1])
# 提取球迷效应
attendance_coef = model.params['attendance']
print(f"\n球迷效应:球迷每增加1人,进球增加 {np.exp(attendance_coef)-1:.4%}")
# 边际效应
print(f"从0人到45000人满场,预期进球变化:{np.exp(attendance_coef * 45000):.2f} 倍")

心理学角度——量化“裁判偏袒”

思路:球迷助威不仅影响球员,还影响裁判判罚,通过对比空场与满场的犯规次数、黄牌数量、点球判罚等客观数据。

代码案例:计算客队犯规率差异。

import pandas as pd
import numpy as np
# 模拟数据:每场比赛的主队犯规和客队犯规
data = {
    'match_id': range(100),
    'crowd_type': np.random.choice(['empty', 'full'], 100),  # 空场或满场
    'home_fouls': np.random.poisson(12, 100),
    'away_fouls': np.random.poisson(12, 100),
    'home_yellow': np.random.poisson(1.5, 100),
    'away_yellow': np.random.poisson(2.5, 100),
}
df_foul = pd.DataFrame(data)
# 构造“偏袒指数”:主队犯规 - 客队犯规(负值表示对客队更严格)
df_foul['referee_bias'] = df_foul['home_fouls'] - df_foul['away_fouls']
df_foul['card_bias'] = df_foul['home_yellow'] - df_foul['away_yellow']
# 分组比较
results = df_foul.groupby('crowd_type')[['referee_bias', 'card_bias']].mean()
print("=== 主场球迷对裁判判罚的影响 ===")
print(results)
# 可视化
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
for i, col in enumerate(['referee_bias', 'card_bias']):
    df_foul.boxplot(column=col, by='crowd_type', ax=axes[i])
    axes[i].set_title(col.replace('_', ' ').title())
    axes[i].set_xlabel('Crowd Type')
plt.suptitle('Home Crowd Effect on Referee Decisions')
plt.tight_layout()
plt.show()

全场压迫强度(体能维度)

核心思路:利用跑动距离、冲刺次数、高位压迫成功率来量化球迷的“精神氮泵”效应。

代码案例

import pandas as pd
import numpy as np
# 模拟高精度跑动数据
data = {
    'match_id': range(50),
    'attendance': np.random.choice([0, 45000], 50),
    'team_distance_km': np.random.normal(112, 5, 50),  # 全队跑动距离
    'sprints_count': np.random.poisson(150, 50),         # 冲刺次数
    'high_press_success': np.random.uniform(0.2, 0.6, 50), # 高位压迫成功率
}
df_run = pd.DataFrame(data)
# 添加球迷效应(模拟真实:满场增加跑动)
df_run.loc[df_run['attendance'] > 0, 'team_distance_km'] += np.random.normal(3, 1, (df_run['attendance'] > 0).sum())
df_run.loc[df_run['attendance'] > 0, 'sprints_count'] += np.random.poisson(20, (df_run['attendance'] > 0).sum())
# 相关性分析
print("=== 球迷数量与体能指标相关性 ===")
print(df_run[['attendance', 'team_distance_km', 'sprints_count']].corr()['attendance'])
# 线性回归量化
from sklearn.linear_model import LinearRegression
X = df_run[['attendance']]
y = df_run['team_distance_km']
reg = LinearRegression().fit(X, y)
print(f"\n球迷每增加1万人,全队多跑 {reg.coef_[0]*10000:.2f} 公里")

进阶:因果推断(双重差分法 DID)

如果想做更严谨的因果推断,可以比较同城德比(高关注度)与普通比赛在有无球迷时的差异。

# 双重差分模型
# Y = β0 + β1*Post(有球迷后) + β2*Treatment(重要比赛) + β3*(Post*Treatment) + ε

如何向业务方汇报?

指标维度 量化公式 业务解读
胜率/积分 场均积分差 “满场让球队多拿X分/赛季”
进攻效率 xG差值或进球差值 “球迷帮助球队多进X球”
体能消耗 跑动距离差 “球迷激励球员多跑X公里”
裁判效应 犯规/黄牌差 “主场哨存在/不存在”

最终交付报告模板

满场球迷的边际效应:
- 场均积分提升:+0.45分(p<0.01)
- 进球数提升:+0.35球/场
- 对手红牌概率:+12%
- 全队跑动距离:多 3.2 公里
主场球迷相当于给球队带来了“隐形外援”,价值约等于+0.5个联赛积分/场。

这些代码可以作为函数封装,接入实时比赛数据API(如 Opta、StatsBomb)即可投入实际使用。

抱歉,评论功能暂时关闭!