足球比赛中量化主队球迷人数影响的Python案例分析
问题背景
在足球比赛中,主场优势(Home Advantage)是公认存在的现象,但"主场优势"到底有多少来自球迷人数本身?这是一个可以量化的数据科学问题。

本文通过构建一个多元回归模型,量化主队球迷人数对比赛结果(如主队进球数、胜率)的影响。
数据准备
假设我们有一份比赛数据集,字段包括:
| 字段 | 说明 |
|---|---|
home_goals |
主队进球数 |
away_goals |
客队进球数 |
attendance |
现场观众人数 |
stadium_capacity |
球场容量 |
home_team_strength |
主队实力评分(如Elo) |
away_team_strength |
客队实力评分 |
is_derby |
是否德比战 |
weather |
天气状况 |
关键点:直接用 attendance 会混淆"球队吸引力"和"球迷影响"——强队本来观众就多,也本来就更可能赢,所以需要做控制变量。
核心建模思路
方法1:回归模型(推荐)
import pandas as pd
import numpy as np
import statsmodels.api as sm
from sklearn.preprocessing import StandardScaler
# 1. 读取数据
df = pd.read_csv("matches.csv")
# 2. 构造关键变量
df['goal_diff'] = df['home_goals'] - df['away_goals']
df['strength_diff'] = df['home_team_strength'] - df['away_team_strength']
df['attendance_rate'] = df['attendance'] / df['stadium_capacity'] # 上座率,消除球场大小差异
# 3. 标准化,便于比较系数
scaler = StandardScaler()
df[['attendance_rate_z', 'strength_diff_z']] = scaler.fit_transform(
df[['attendance_rate', 'strength_diff']]
)
# 4. 构建回归模型
X = df[['attendance_rate_z', 'strength_diff_z', 'is_derby']]
X = sm.add_constant(X)
y = df['goal_diff']
model = sm.OLS(y, X).fit()
print(model.summary())
结果解读示例:
coef std err t P>|t|
const 0.15 0.05 3.0 0.003
attendance_rate_z 0.28 0.06 4.67 0.000 ← 关键系数
strength_diff_z 0.55 0.05 11.0 0.000
is_derby -0.10 0.08 -1.25 0.211
含义:上座率每提高1个标准差,主队净胜球增加 28 个,假设某场上座率从50%提升到90%(约1个标准差),主队净胜球平均多0.28个。
方法2:准自然实验——空场比赛(COVID案例)
2020年疫情期间大量比赛空场进行,这是天然的实验:
# 分组:有观众 vs 无观众
df['has_crowd'] = (df['attendance'] > 0).astype(int)
# 计算主队优势指标
df['home_advantage'] = df['home_goals'] - df['away_goals']
# 对比
result = df.groupby('has_crowd')['home_advantage'].agg(['mean', 'std', 'count'])
print(result)
典型结果:
| 组别 | 平均净胜球 | 样本量 |
|---|---|---|
| 有观众 | +0.35 | 5000 |
| 无观众 | +0.10 | 800 |
球迷带来的主场优势约为 25 球/场,约占总主场优势的 70%。
方法3:工具变量法(IV)——处理内生性
如果担心"观众多→球队强→赢球"的反向因果,可用天气作为工具变量(下雨→观众少,但不直接影响进球):
from linearmodels.iv import IV2SLS
# 第一阶段:天气预测观众
# 第二阶段:用预测的观众量估计对净胜球的影响
iv_model = IV2SLS.from_formula(
'goal_diff ~ 1 + strength_diff + is_derby + [attendance_rate ~ rain]',
data=df
).fit()
print(iv_model.summary)
分位数分析(更精细)
不同上座率区间的影响可能非线性的:
df['attendance_bin'] = pd.cut(
df['attendance_rate'],
bins=[0, 0.4, 0.6, 0.8, 1.0],
labels=['低(0-40%)', '中(40-60%)', '高(60-80%)', '满(80-100%)']
)
summary = df.groupby('attendance_bin')['goal_diff'].agg(['mean', 'count'])
print(summary)
可能发现:上座率在 60-80% 区间时影响最大,达到80%后边际效应递减(球迷噪音"饱和")。
最终量化结论模板
综合以上分析,可以得到如下结论:
在控制球队实力、德比、天气等因素后:
- 上座率每提升 10个百分点,主队净胜球平均增加 05-0.08 个
- 空场相比满场,主队优势损失约 2-0.3 球/场
- 换算为胜率:满场主队胜率比空场高约 8-12 个百分点
注意事项(避免踩坑)
- 内生性问题:观众多可能是因为球队强,必须用控制变量或IV
- 样本选择偏差:豪门球场大、观众多,需引入球队固定效应
- 非线性:观众影响可能是边际递减的,可用分段回归
- 疫情数据特殊:空场不仅减少了球迷,还改变了球员心理,解释时需谨慎
- 用上座率而非绝对人数:绝对人数会被球场容量干扰
延伸方向
- 面板数据模型:
PanelOLS加球队固定效应,剔除球队长期实力差异 - 贝叶斯分层模型:适合样本不均的联赛
- 因果推断:使用 DID(双重差分) 对比疫情前后同一球队表现
- 机器学习:XGBoost + SHAP 值可视化球迷人数的贡献度