本文目录导读:

- 案例一:基于线性回归的边际影响分析
- 案例二:使用泊松回归预测进球数
- 案例三:量化“第12人”效应——主客场转换的边际影响
- 案例四:非线性效应与阈值检测
- 案例五:机器学习方法(因果推断)
- 关键注意事项
- 推荐的数据来源
这是一个很有意思的足球数据分析问题,要量化“主队球迷人数”对比赛结果的影响,通常需要将上座人数(或主场氛围代理变量)转化为可建模的特征,并与其他因素(如球队实力)剥离。
以下是几个Python量化分析的经典案例和步骤,从简单到复杂:
基于线性回归的边际影响分析
目标:在控制主客队实力(如积分、球员身价)后,找出每增加1万名观众,主队预期进球或赢球概率的变化。
数据准备(假设你有历史比赛数据):
attendance:上座人数home_goals:主队进球away_goals:客队进球home_team_rank:主队联赛排名(或积分)away_team_rank:客队联赛排名stadium_capacity:球场容量(用于归一化)
Python代码步骤:
import pandas as pd
import statsmodels.api as sm
# 1. 数据加载与特征工程
df = pd.read_csv('football_matches.csv')
# 创建主场优势变量:上座率(消除球场大小差异)
df['attendance_ratio'] = df['attendance'] / df['stadium_capacity']
# 创建球队实力差
df['strength_diff'] = df['home_team_rank'] - df['away_team_rank'] # 排名越低越强
# 2. 定义因变量:主场净胜球
df['goal_diff'] = df['home_goals'] - df['away_goals']
# 3. 多元线性回归
X = df[['attendance_ratio', 'strength_diff']]
X = sm.add_constant(X) # 添加截距项
y = df['goal_diff']
model = sm.OLS(y, X).fit()
print(model.summary())
# 4. 解读结果:
# - attendance_ratio的系数:表示当上座率每增加10%,主队净胜球平均变化多少
# - p值检验:该系数是否统计显著(lt;0.05表示显著)
输出解读示例:
- 系数为0.8,p<0.01:上座率每提高10%,主队预期净胜球增加0.08个。
使用泊松回归预测进球数
足球进球数符合泊松分布,用泊松回归更合理。
import statsmodels.api as sm
import statsmodels.formula.api as smf
# 使用公式API
model_poisson = smf.glm(
formula="home_goals ~ attendance_ratio + strength_diff + home_goals_lag",
data=df,
family=sm.families.Poisson()
).fit()
# 查看系数
print(model_poisson.params)
优点:直接建模进球数,更符合足球统计特性。
量化“第12人”效应——主客场转换的边际影响
核心思路:比较同一支球队在空场(如疫情期)与满场时的表现差异。
数据需求:
- 2020-2021赛季(空场) vs 2018-2019赛季(有观众)
Python代码实现:
# 1. 创建哑变量
df['has_audience'] = (df['season'] != '2020-2021').astype(int) # 1=有观众,0=空场
# 2. 固定效应模型(控制球队自身差异)
import statsmodels.api as sm
from statsmodels.regression.linear_model import PanelOLS
# 需要数据为面板格式
df = df.set_index(['home_team', 'match_id'])
model_fe = PanelOLS(
df['home_goals'],
df[['has_audience', 'strength_diff']],
entity_effects=True # 控制球队固定效应
).fit()
print(model_fe)
解读:has_audience 的系数即为“观众存在”带来的主场进球增加量,欧洲五大联赛研究通常显示该系数在0.2-0.4之间(即每场多进0.2-0.4球)。
非线性效应与阈值检测
球迷影响可能不是线性的:当人数超过一定阈值(如坐满80%),效应会显著增强。
# 分段回归(寻找断点)
from scipy import optimize
import numpy as np
def piecewise_linear(x, breakpoint, slope1, slope2):
return np.piecewise(x, [x < breakpoint, x >= breakpoint],
[lambda x: slope1 * x, lambda x: slope2 * x + (slope1-slope2)*breakpoint])
# 使用优化寻找最佳断点
popt, _ = optimize.curve_fit(piecewise_linear, df['attendance_ratio'], df['goal_diff'])
print(f'找到的断点:{popt[0]:.2f},前半段斜率:{popt[1]:.2f},后半段斜率:{popt[2]:.2f}')
日常应用:如果发现阈值在0.75(75%上座率),则建议俱乐部尽量将上座率维持在75%以上以最大化主场优势。
机器学习方法(因果推断)
使用双重机器学习(Double ML)或工具变量法,排除“强队吸引更多观众”的逆向因果。
from sklearn.ensemble import GradientBoostingRegressor
from econml.dml import DML
# 定义:观众数为处理变量T,球队实力为混淆变量W,结果Y为净胜球
est = DML(model_y=GradientBoostingRegressor(),
model_t=GradientBoostingRegressor(),
model_final=GradientBoostingRegressor())
est.fit(y=df['goal_diff'], T=df['attendance_ratio'], W=df[['strength_diff', 'stadium_capacity']])
# 得到因果效应
print(est.effect())
结果:得出“观众人数对净胜球的因果效应”(而非相关性)。
关键注意事项
-
数据清洗:
- 去除德比战数据(球迷情绪极端)。
- 去除杯赛决赛(中立场地)。
-
控制变量:
- 球队近期状态(过去5场胜率)。
- 路程距离(客队舟车劳顿)。
- 天气因素(雨雪影响上座率)。
-
稳健性检验:
- 使用不同的衡量指标:上座率 vs 绝对人数。
- 更换模型:线性回归 vs 泊松回归 vs 随机森林。
推荐的数据来源
- Kaggle:European Soccer Database (含观众数据)
- StatsBomb:免费公开数据(不含观众但可结合其他数据源)
- Transfermarkt:官方上座数据(需爬虫)
如果你想快速得到一个可解释的答案,案例一(多元线性回归) 就足够了,如果追求学术严谨性,案例五(因果推断) 更合适,最简单的量化结论大概是:平均每增加1万观众,主队进球期望增加约0.1~0.2个(该数值因联赛而异)。
你可以根据自己手头的数据类型(是否有空场数据、是否包含球队实力排名)选择最适合的案例,如果需要具体代码调试,可以补充你的数据样例列名,我可以帮你适配代码。