实用脚本统计禁区内射门次数对比?

wen 实用脚本 3

统计禁区内射门次数对比的脚本

下面给你一个完整可用的 Python 脚本,用于统计并对比两支球队(或两名球员)在禁区内的射门次数,支持从 CSV 读取数据,也提供模拟数据示例。

实用脚本统计禁区内射门次数对比?


数据格式(CSV)

假设你有一份射门事件数据 shots.csv,字段如下:

match_id,team,player,minute,x,y,body_part,is_goal
1,TeamA,Alice,12,88.5,34.2,right_foot,1
1,TeamA,Bob,25,92.1,40.0,left_foot,0
1,TeamB,Carol,33,45.0,30.0,head,0
1,TeamB,Dave,67,85.0,50.0,right_foot,1
...
  • x, y 为球场坐标(0–100 × 0–100,进攻方向向右)。
  • 禁区判定:以球场宽度方向为 y,长度方向为 x,标准禁区内区域为:
    • x ≥ 83(距底线 17 米内,约合 100 坐标制的 83)
    • y ∈ [21, 79](禁区宽度约 58 米,居中)

脚本代码

import pandas as pd
from collections import defaultdict
# ================= 配置 =================
CSV_PATH = "shots.csv"
PITCH_LEN = 100
PITCH_WID = 100
# 禁区判定参数(可调)
BOX_X_MIN = 83        # 距底线 17/105≈16.2,取整数 83
BOX_Y_MIN = 21        # 禁区两侧边界
BOX_Y_MAX = 79
# ================= 工具函数 =================
def in_penalty_box(x, y):
    """判断射门点是否在禁区内(进攻方向向右)"""
    return (x >= BOX_X_MIN) and (BOX_Y_MIN <= y <= BOX_Y_MAX)
# ================= 主逻辑 =================
def analyze_shots(df):
    # 标记是否在禁区内
    df["in_box"] = df.apply(lambda r: in_penalty_box(r["x"], r["y"]), axis=1)
    stats = defaultdict(lambda: {"total": 0, "in_box": 0, "goals_in_box": 0})
    for _, row in df.iterrows():
        key = row["team"]        # 也可改成 row["player"]
        stats[key]["total"] += 1
        if row["in_box"]:
            stats[key]["in_box"] += 1
            if row["is_goal"] == 1:
                stats[key]["goals_in_box"] += 1
    # 生成对比表
    rows = []
    for team, s in stats.items():
        pct = (s["in_box"] / s["total"] * 100) if s["total"] else 0
        rows.append({
            "Team": team,
            "Total Shots": s["total"],
            "Shots in Box": s["in_box"],
            "In-Box %": round(pct, 1),
            "Goals in Box": s["goals_in_box"],
        })
    return pd.DataFrame(rows).sort_values("Shots in Box", ascending=False)
# ================= 入口 =================
if __name__ == "__main__":
    try:
        df = pd.read_csv(CSV_PATH)
    except FileNotFoundError:
        print("⚠️ 未找到 CSV,使用模拟数据演示")
        df = pd.DataFrame({
            "match_id": [1]*8,
            "team": ["TeamA","TeamA","TeamA","TeamA","TeamB","TeamB","TeamB","TeamB"],
            "player": ["A1","A2","A1","A3","B1","B2","B1","B3"],
            "minute": [12,25,55,78,33,67,80,90],
            "x": [88.5, 60.0, 92.1, 95.0, 45.0, 85.0, 90.0, 80.0],
            "y": [34.2, 50.0, 40.0, 30.0, 30.0, 50.0, 60.0, 25.0],
            "body_part": ["right_foot","left_foot","right_foot","head","head","right_foot","left_foot","head"],
            "is_goal": [1,0,0,1,0,1,0,0],
        })
    result = analyze_shots(df)
    print("\n=== 禁区内射门对比 ===")
    print(result.to_string(index=False))

输出示例

=== 禁区内射门对比 ===
 Team  Total Shots  Shots in Box  In-Box %  Goals in Box
TeamA            4             3      75.0             2
TeamB            4             2      50.0             1

进阶扩展建议

需求 修改方式
按球员对比 把 key = row["team"] 改为 row["player"]
按比赛分组 df.groupby("match_id").apply(analyze_shots)
支持左右半场进攻 右半场用标准判定,左半场坐标镜像:x = 100 - x
统计xG或射门距离 增加列并按禁区、非禁区聚合
输出图表 用 matplotlib 或 pandas.plot.bar 可视化 In-Box 对比

坐标判定说明(重要)

  • 若你的数据是 Opta / StatsBomb 坐标系(0–120 × 0–80 或类似),需按比例调整:
    • StatsBomb 标准禁区:x ∈ [102, 120],y ∈ [18, 62]
    • 只需改 BOX_X_MIN / BOX_Y_MIN / BOX_Y_MAX 三个常量即可。
  • 上方默认值适用于 0–100 归一化坐标,进攻方向统一为向右(x 增大方向)。

需要我把这个脚本改成可视化版本(柱状图),或适配 StatsBomb 数据的具体格式吗?

上一篇根据实用脚本,反击效率哪队更出色?

下一篇当前分类已是最新一篇

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