实用脚本统计传球成功率哪队更高?

wen 实用脚本 2

统计传球成功率哪队更高的实用脚本

下面给你一个可直接运行的 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)或按半场 / 按球员 / 按传球类型细分再给脚本吗?告诉我你手上的数据字段,我可以直接适配。

抱歉,评论功能暂时关闭!