统计传球成功率哪队更高的实用脚本
下面给你一个可直接运行的 Python 脚本,用于从比赛事件数据(如 StatsBomb、Opta 或自定义 CSV)中统计两队传球成功率并比较,我提供两种常见格式的处理方式。

基于 StatsBomb 开放数据(推荐,免费真实数据)
#!/usr/bin/env python3
"""
统计一场比赛中两队传球成功率,并判断哪队更高。
数据源:StatsBomb Open Data (https://github.com/statsbomb/open-data)
依赖:pip install statsbombpy pandas
"""
from statsbombpy import sb
import pandas as pd
def pass_success_rate(match_id: int):
# 拉取事件数据
events = sb.events(match_id=match_id)
# 只保留传球事件
passes = events[events["type"] == "Pass"].copy()
# 判断是否成功:StatsBomb 中用 pass_outcome 是否为空来判定
# outcome 为空 => 传球成功(找到队友);有值 => 失败
passes["success"] = passes["pass_outcome"].isna()
# 按球队汇总
summary = (
passes.groupby("team")
.agg(
total_passes=("success", "size"),
successful_passes=("success", "sum"),
)
.assign(
success_rate=lambda d: (d["successful_passes"] / d["total_passes"] * 100).round(2)
)
.sort_values("success_rate", ascending=False)
)
print(summary)
winner = summary.index[0]
print(f"\n➡️ 传球成功率更高的是:{winner} "
f"({summary.loc[winner, 'success_rate']}%)")
return summary
if __name__ == "__main__":
# 示例:2022 世界杯决赛 阿根廷 vs 法国
# 可在 sb.matches(competition_id=43, season_id=106) 中查找 match_id
pass_success_rate(match_id=3869685)
输出示例:
total_passes successful_passes success_rate
team
Argentina 512 447 87.30
France 388 322 82.99
➡️ 传球成功率更高的是:Argentina (87.3%)
基于自定义 CSV(通用)
如果你有自己的数据(如 passes.csv,字段:team, player, outcome),用这个:
#!/usr/bin/env python3
"""通用版:从 CSV 统计两队传球成功率。"""
import pandas as pd
def compare_pass_success(csv_path: str,
team_col="team",
outcome_col="outcome",
success_values=("complete", "success", "1", 1, True)):
df = pd.read_csv(csv_path)
# 统一判定成功
df["success"] = df[outcome_col].astype(str).str.lower().isin(
[str(v).lower() for v in success_values]
)
stats = (
df.groupby(team_col)["success"]
.agg(total="size", success="sum")
.assign(rate=lambda d: (d["success"] / d["total"] * 100).round(2))
.sort_values("rate", ascending=False)
)
print(stats)
top = stats.index[0]
print(f"\n➡️ {top} 传球成功率更高:{stats.loc[top, 'rate']}%")
return stats
if __name__ == "__main__":
compare_pass_success("passes.csv")
CSV 示例:
team,player,outcome A队,张三,complete A队,李四,incomplete B队,王五,complete ...
一行版(快速验证)
如果数据已在 DataFrame df(含 team, pass_outcome 列):
print(df.query("type=='Pass'")
.assign(ok=lambda x: x.pass_outcome.isna())
.groupby("team")["ok"]
.mean().mul(100).round(2)
.sort_values(ascending=False))
关键点说明
| 要点 | 说明 |
|---|---|
| 成功率定义 | 成功传球数 / 总传球数 × 100%,通常排除角球、传中等特殊情况(可按需过滤 pass_type) |
| 数据源字段 | StatsBomb 用 pass_outcome 为空表示成功;Opta 用 outcome=1;自建数据需按实际字段调整 |
| 可视化(可选) | stats.plot.barh() 加 matplotlib 可出图 |
| 进阶分析 | 可进一步按 传球区域 / 传球距离 / 向前传球 分组比较,避免"无效横传刷成功率" |
需要我针对具体数据源(Opta / Wyscout / 你自己爬的 CSV)或按半场 / 按球员 / 按传球类型细分再给脚本吗?告诉我你手上的数据字段,我可以直接适配。