本文目录导读:

在足球数据分析中,进攻三区通常指距对方球门35米或30米以内的区域,也就是前场进攻区域,量化进攻三区效率值,核心目标是回答一个问题:球队/球员把球推进到进攻三区后,究竟制造了多少实质威胁?
下面是一套可以直接落地的脚本化计算框架。
先定义指标框架
效率值 = 产出 / 投入,建议拆成三层:
| 层级 | 投入指标 | 产出指标 |
|---|---|---|
| 推进 | 进入三区次数 | |
| 制造 | 三区内传球数、触球数 | 禁区内传球、关键传球 |
| 终结 | 三区内控球时长 | 射门、xG、进球 |
核心效率公式:
三区效率值 = (射门数 × 0.4 + xG × 0.4 + 进球 × 0.2) / 进入三区次数 × 100
权重可按联赛数据回归校准,这里给的是通用起点。
数据来源与字段要求
需要的事件数据(StatsBomb / Opta / Wyscout 格式均可):
# 每条事件至少包含
{
"match_id": ,
"team": ,
"player": ,
"event_type": "pass|carry|shot|touch",
"x": , # 球场坐标 0-100 或 0-120
"y": ,
"end_x": ,
"end_y": ,
"xg": , # 仅射门有
"outcome":
}
核心脚本
import pandas as pd
import numpy as np
# ---------- 1. 定义进攻三区 ----------
PITCH_LENGTH = 105 # 米
THIRD_ZONE_X = PITCH_LENGTH * (2/3) # 70米处,即对方三区起点
def in_final_third(x):
return x >= THIRD_ZONE_X
def in_box(x, y):
# 标准禁区内:距底线16.5米,宽40.32米
return x >= PITCH_LENGTH - 16.5 and 13.84 <= y <= 54.16
# ---------- 2. 标记事件 ----------
def tag_events(df):
df['in_third'] = df['x'].apply(in_final_third)
df['in_box'] = df.apply(lambda r: in_box(r['x'], r['y']), axis=1)
return df
# ---------- 3. 计算球队三区效率 ----------
def final_third_efficiency(df, team):
d = df[(df['team'] == team) & (df['in_third'])].copy()
entries = d[d['event_type'].isin(['pass','carry']) &
(d['x'] < THIRD_ZONE_X + 5)].shape[0] # 刚跨入三区
passes = d[d['event_type'] == 'pass'].shape[0]
box_passes = d[(d['event_type'] == 'pass') & (d['in_box'])].shape[0]
shots = d[d['event_type'] == 'shot'].shape[0]
xg = d[d['event_type'] == 'shot']['xg'].sum()
goals = d[(d['event_type'] == 'shot') & (d['outcome']=='goal')].shape[0]
# 效率值(0-100)
efficiency = (shots*0.4 + xg*0.4 + goals*0.2) / max(entries,1) * 100
return {
'team': team,
'entries': entries,
'passes_in_third': passes,
'box_passes': box_passes,
'shots': shots,
'xg': round(xg,2),
'goals': goals,
'efficiency': round(efficiency,2),
'box_pass_rate': round(box_passes/max(passes,1),3),
'shot_per_entry': round(shots/max(entries,1),3)
}
# ---------- 4. 批量跑全联赛 ----------
results = [final_third_efficiency(df, t) for t in df['team'].unique()]
rank = pd.DataFrame(results).sort_values('efficiency', ascending=False)
print(rank)
进阶:加入控球时长与对手强度
三区控球时长(用事件时间戳)
d['dt'] = d['timestamp'].diff().fillna(0) possession_time = d[d['team']==team]['dt'].sum() efficiency_per_min = shots / (possession_time/60)
对手强度修正
# 对手防守强度系数(可用对手失球数倒数归一化) opp_factor = 1 / (opp_goals_conceded / league_avg_conceded) adjusted_eff = efficiency * opp_factor
场地因素
主客场分别统计,或加入 home_away 哑变量回归。
可视化输出
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(10,6))
ax.barh(rank['team'], rank['efficiency'], color='steelblue')
ax.set_xlabel('进攻三区效率值')
ax.set_title('各队进攻三区效率排名')
plt.tight_layout()
plt.savefig('third_zone_efficiency.png', dpi=150)
指标解读注意事项
- 样本量要求:单场样本太小,建议至少10场滚动窗口。
- 风格偏差:控球型球队 entries 多但效率可能低;反击型球队 entries 少但效率高,需结合 entries 绝对值一起看。
- 权重校准:0.4/0.4/0.2 是经验值,建议用逻辑回归或泊松模型对“是否进球”做拟合来反推权重。
- 坐标归一化:不同数据商坐标体系不同(0-100 vs 0-120),务必统一。
如果你告诉我你用的是哪家数据(StatsBomb / Opta / 自采),我可以把坐标和字段映射改写成对应版本,并加上滚动窗口和对手修正的完整脚本。