统计脚后跟传球成功次数的脚本方案
你问的是"实际脚本统计脚后跟传球",我理解你想用代码从足球比赛数据(如事件数据、追踪数据)中自动统计"脚后跟传球(backheel pass)"的成功次数,下面给你一个可落地的方案。

数据来源选择
| 数据源 | 是否含脚后跟标签 | 说明 |
|---|---|---|
| StatsBomb Open Data | ✅ 有 pass.body_part 和 technique |
免费,推荐 |
| Opta / Stats Perform | ✅ 有 qualifier | 商业 |
| Wyscout | ⚠️ 部分 | 需映射 |
| 追踪数据(坐标) | ❌ 需自己判定 | 需几何规则 |
最省事:StatsBomb 的 pass.technique 字段里有 "Backheel" 值,直接过滤即可。
核心脚本(基于 StatsBomb 事件数据)
import pandas as pd
from statsbombpy import sb
def count_backheel_passes(match_id: int):
events = sb.events(match_id=match_id)
# 只取传球事件
passes = events[events['type'] == 'Pass'].copy()
# 提取 technique 字段(可能是 list 或 str)
def get_tech(t):
if isinstance(t, list):
return t
if isinstance(t, str):
return [t]
return []
passes['tech_list'] = passes['pass_technique'].apply(get_tech)
# 筛选脚后跟传球
backheels = passes[passes['tech_list'].apply(lambda x: 'Backheel' in x)]
# 判定成功:StatsBomb 中传球成功 = 没有 pass_outcome(即 outcome 为空)
backheels = backheels.copy()
backheels['success'] = backheels['pass_outcome'].isna()
total = len(backheels)
success = int(backheels['success'].sum())
# 按球员统计
by_player = (backheels.groupby('player')['success']
.agg(['count', 'sum'])
.rename(columns={'count': 'attempts', 'sum': 'successes'}))
by_player['rate'] = (by_player['successes'] / by_player['attempts']).round(2)
print(f"比赛 {match_id}: 脚后跟传球 {total} 次,成功 {success} 次,成功率 {success/total:.1%}" if total else "无脚后跟传球")
return backheels, by_player
# 示例
match_id = 3788741 # 可换成任意 StatsBomb 比赛ID
backheels, by_player = count_backheel_passes(match_id)
print(by_player.sort_values('successes', ascending=False))
如果没有 technique 标签(用追踪数据判定)
若只有坐标数据,用几何规则近似判定"脚后跟传球":
import numpy as np
def is_backheel_pass(passer_pos, receiver_pos, pass_end, attacking_dir=1):
"""
passer_pos: (x, y) 传球者位置
pass_end: (x, y) 球落点
attacking_dir: +1 表示向右进攻
规则:球的行进方向与球员朝向相反 → 近似脚后跟
"""
dx = (pass_end[0] - passer_pos[0]) * attacking_dir
# 球向后传(与进攻方向相反)且距离短,才可能是脚后跟
if dx > -2: # 不是向后传
return False
dist = np.hypot(pass_end[0]-passer_pos[0], pass_end[1]-passer_pos[1])
return dist < 15 # 短距离回做
⚠️ 追踪数据判定误差大,只能算"疑似脚后跟",建议只用事件数据做正式统计。
批量统计整届赛事
def tournament_backheel_stats(competition_id, season_id):
matches = sb.matches(competition_id=competition_id, season_id=season_id)
all_rows = []
for mid in matches['match_id']:
bh, _ = count_backheel_passes(mid)
if len(bh):
bh['match_id'] = mid
all_rows.append(bh)
if not all_rows:
return pd.DataFrame()
df = pd.concat(all_rows)
summary = (df.groupby('player')
.agg(attempts=('success','size'), successes=('success','sum')))
summary['rate'] = (summary.successes/summary.attempts).round(2)
return summary.sort_values('successes', ascending=False)
# 例:2022世界杯
# print(tournament_backheel_stats(43, 106))
注意事项
- 字段名版本差异:
statsbombpy不同版本列名可能是pass_technique或嵌套在pass字典里,先print(events.columns)确认。 - "成功"定义:StatsBomb 中传球成功 =
pass_outcome为空(未出界/未被断/未丢球权),若你的数据源用accurate=True/False,改判据即可。 - 脚后跟 ≠ 所有回传:一定要用 technique 标签,别用方向规则替代,否则会把普通回传也算进去。
- 边界情况:脚后跟传球被犯规中断、形成射门等情况,按你的统计口径决定算不算"成功"。
需要我帮你改成 Opta XML 解析版、Wyscout API 版,或加上可视化(球员脚后跟传球热图)吗?告诉我你的数据源,我直接给你对应脚本。