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

wen 实用脚本 4

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

下面给你一个完整的 Python 脚本,用于统计两队(或两名球员)在禁区内射门次数的对比,适用于足球赛后数据分析。

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


基于事件数据(推荐)

假设你有比赛事件数据(CSV),字段包含:team、player、x、y、event_type,禁区内一般定义为:进攻方向球门中心 (x=105, y=34),禁区约为距球门 16.5m 范围。

import pandas as pd
import numpy as np
# ============ 1. 读取数据 ============
# 示例列: match_id, team, player, minute, event_type, x, y
df = pd.read_csv("match_events.csv")
# ============ 2. 只保留射门 ============
shots = df[df["event_type"].str.lower().isin(["shot", "射门"])].copy()
# ============ 3. 判断是否在禁区内 ============
# 假设球场坐标 105 x 68,进攻方向 +x,球门中心 (105, 34)
GOAL_X, GOAL_Y = 105.0, 34.0
PENALTY_DEPTH = 16.5   # 禁区纵深
PENALTY_WIDTH = 40.32  # 禁区宽度
def in_penalty_area(x, y):
    """判断是否在禁区内"""
    if pd.isna(x) or pd.isna(y):
        return False
    # 距底线深度
    dx = GOAL_X - x
    # 距中轴横向距离
    dy = abs(GOAL_Y - y)
    return (0 <= dx <= PENALTY_DEPTH) and (dy <= PENALTY_WIDTH / 2)
shots["in_box"] = shots.apply(lambda r: in_penalty_area(r["x"], r["y"]), axis=1)
# ============ 4. 按球队统计 ============
box_shots   = shots[shots["in_box"]].groupby("team").size()
all_shots   = shots.groupby("team").size()
summary = pd.DataFrame({
    "禁区内射门": box_shots,
    "总射门":     all_shots,
}).fillna(0).astype(int)
summary["禁区外射门"] = summary["总射门"] - summary["禁区内射门"]
summary["禁区占比"]   = (summary["禁区内射门"] / summary["总射门"] * 100).round(1).astype(str) + "%"
print("\n===== 禁区内射门对比 =====")
print(summary)
# ============ 5. 两队横向对比 ============
teams = summary.index.tolist()
if len(teams) >= 2:
    t1, t2 = teams[0], teams[1]
    print(f"\n【{t1}】 vs 【{t2}】")
    print(f"禁区内射门: {summary.loc[t1,'禁区内射门']}  -  {summary.loc[t2,'禁区内射门']}")
    print(f"总射门:     {summary.loc[t1,'总射门']}  -  {summary.loc[t2,'总射门']}")
    print(f"禁区占比:   {summary.loc[t1,'禁区占比']}  vs  {summary.loc[t2,'禁区占比']}")

输出示例:

===== 禁区内射门对比 =====
     禁区内射门  总射门  禁区外射门  禁区占比
A队          9     14         5    64.3%
B队          4     11         7    36.4%

基于热图 / 坐标点直接统计(无事件类型)

如果你只有射门点的坐标数据(比如从 StatsBomb、Opta、Wyscout 导出的 shot events):

import pandas as pd
# 假设 shots.csv: 列为 team, x, y
df = pd.read_csv("shots.csv")
# StatsBomb 坐标系: x∈[0,120], y∈[0,80],禁区约 x≥102, 18≤y≤62
def in_box_statsbomb(x, y):
    return x >= 102 and 18 <= y <= 62
df["in_box"] = df.apply(lambda r: in_box_statsbomb(r["x"], r["y"]), axis=1)
result = df.groupby("team")["in_box"].agg(
    禁区内射门="sum",
    总射门="count"
)
result["禁区外射门"] = result["总射门"] - result["禁区内射门"]
print(result)

命令行一行统计(快速版)

# 假设 CSV 已带 in_box 列 (0/1)
awk -F',' 'NR>1 {total[$1]++; if($5==1) box[$1]++} 
END {for (t in total) printf "%s: 禁区内 %d / 总射门 %d\n", t, box[t], total[t]}' shots.csv

坐标系对照表(不同数据源禁区判断)

数据源 x 范围 球门方向 禁区判断
StatsBomb 0–120 +x x ≥ 102 且 18 ≤ y ≤ 62
Opta 0–100 +x x ≥ 83 且 21.1 ≤ y ≤ 78.9
Wyscout 0–100 +x x ≥ 84 且 21 ≤ y ≤ 79
自定义 105×68 0–105 +x x ≥ 88.5 且 13.84 ≤ y ≤ 54.16

注:若进攻方向为 -x(反向),需先 x = 105 - x 翻转。


建议扩展

  1. 按时间段:加 period 字段,统计上/下半场对比
  2. 按球员:groupby(["team","player"])
  3. xG 加权:禁区内射门乘 xG 值,得到"期望进球对比"
  4. 可视化:用 mplsoccer 画球场 + 射门散点图

需要哪个扩展版本(如 mplsoccer 可视化 或 含 xG 加权),告诉我具体数据源格式,我可以直接给你定制脚本。

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