实用脚本统计任意球直接得分几次?

wen 实用脚本 3

任意球直接得分统计脚本

下面给你一个可直接运行的 Python 脚本,用于统计足球比赛数据中「任意球直接得分」的次数,核心判断逻辑是:进球方式为任意球 且 无助攻(即非间接任意球/配合进球)。

实用脚本统计任意球直接得分几次?


脚本代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统计任意球直接得分次数
用法:
    python fk_goal_stats.py events.csv
    python fk_goal_stats.py events.csv --player "梅西"
CSV 需包含字段(列名可自定义,见 COLUMN_MAP):
    match_id, minute, team, player, event_type, sub_type, assist_player
"""
import csv
import sys
import argparse
from collections import defaultdict
# ===== 列名映射:左边是脚本内部用名,右边是你 CSV 里的实际列名 =====
COLUMN_MAP = {
    "match_id":     "match_id",
    "minute":       "minute",
    "team":         "team",
    "player":       "player",
    "event_type":   "event_type",   # Goal / Shot
    "sub_type":     "sub_type",     # Free Kick / Penalty / Open Play
    "assist_player": "assist_player" # 助攻者,空表示无助攻
}
# 判定「任意球」的关键词(大小写不敏感)
FREE_KICK_KEYWORDS = ["free kick", "free-kick", "freekick", "任意球"]
GOAL_KEYWORDS      = ["goal", "进球"]
def is_free_kick(text: str) -> bool:
    t = (text or "").strip().lower()
    return any(k in t for k in FREE_KICK_KEYWORDS)
def is_goal(text: str) -> bool:
    t = (text or "").strip().lower()
    return any(k in t for k in GOAL_KEYWORDS)
def load_events(path):
    """读取 CSV,返回字典列表(键统一为内部名)"""
    events = []
    with open(path, newline="", encoding="utf-8-sig") as f:
        reader = csv.DictReader(f)
        for row in reader:
            events.append({
                key: (row.get(col_name, "") or "").strip()
                for key, col_name in COLUMN_MAP.items()
            })
    return events
def count_direct_fk_goals(events, player_filter=None):
    """
    返回:
      total: int  任意球直接得分总数
      detail: list  每一条命中的记录
    """
    detail = []
    for e in events:
        if not is_goal(e["event_type"]):
            continue
        if not is_free_kick(e["sub_type"]):
            continue
        # 有助攻 => 视为间接任意球配合进球,不算「直接得分」
        if e["assist_player"]:
            continue
        if player_filter and player_filter not in e["player"]:
            continue
        detail.append(e)
    return len(detail), detail
def main():
    parser = argparse.ArgumentParser(description="统计任意球直接得分次数")
    parser.add_argument("csv_file", help="事件数据 CSV 路径")
    parser.add_argument("--player", default=None, help="只统计某球员(模糊匹配)")
    parser.add_argument("--by-team", action="store_true", help="按球队分组统计")
    parser.add_argument("--by-player", action="store_true", help="按球员分组统计")
    args = parser.parse_args()
    events = load_events(args.csv_file)
    total, detail = count_direct_fk_goals(events, args.player)
    print(f"\n=== 任意球直接得分统计 ===")
    print(f"总次数: {total}")
    if detail:
        print("\n明细:")
        for e in detail:
            print(f"  第{e['minute']}分钟 | {e['team']} | {e['player']} "
                  f"| match={e['match_id']}")
    if args.by_team:
        agg = defaultdict(int)
        for e in detail:
            agg[e["team"]] += 1
        print("\n按球队:")
        for team, n in sorted(agg.items(), key=lambda x: -x[1]):
            print(f"  {team}: {n}")
    if args.by_player:
        agg = defaultdict(int)
        for e in detail:
            agg[e["player"]] += 1
        print("\n按球员:")
        for p, n in sorted(agg.items(), key=lambda x: -x[1]):
            print(f"  {p}: {n}")
if __name__ == "__main__":
    main()

示例 CSV 格式

events.csv:

match_id,minute,team,player,event_type,sub_type,assist_player
M001,23,阿根廷,梅西,Goal,Free Kick,
M001,45,法国,格列兹曼,Goal,Free Kick,姆巴佩
M002,67,巴西,内马尔,Goal,Penalty,
M002,80,德国,克罗斯,Goal,Free Kick,

运行:

python fk_goal_stats.py events.csv
python fk_goal_stats.py events.csv --by-player
python fk_goal_stats.py events.csv --player 梅西

输出:

=== 任意球直接得分统计 ===
总次数: 2
明细:
  第23分钟 | 阿根廷 | 梅西 | match=M001
  第80分钟 | 德国 | 克罗斯 | match=M002

注意:第 45 分钟格列兹曼那球 sub_type=Free Kick 但有助攻 姆巴佩,属于任意球配合进球,不计入直接得分。


关键判定规则说明

规则 说明
event_type 含 Goal 是进球
sub_type 含 Free Kick 是任意球
assist_player 为空 无助攻 → 直接得分
有助攻 间接任意球 / 配合进球,排除

可根据你的数据源(Opta / StatsBomb / 懂球帝 / 自制表格)修改 COLUMN_MAP 和关键词即可适配。


如果你用的是 StatsBomb 开放数据

StatsBomb 的射门事件里,任意球直接射门特征是:

  • shot.type.name == "Free Kick"
  • shot.outcome.name == "Goal"
  • shot.freeze_frame 存在(人墙)

对应核心判断:

def is_direct_fk_goal(ev):
    if ev.get("type", {}).get("name") != "Shot":
        return False
    shot = ev.get("shot", {})
    return (shot.get("type", {}).get("name") == "Free Kick"
            and shot.get("outcome", {}).get("name") == "Goal"
            and shot.get("freeze_frame") is not None)  # 有人墙=直接射门

需要我帮你改写成适配 StatsBomb JSON 或 Opta F24 的版本,告诉我数据格式即可。

上一篇实用脚本认为出球门将是现代足球趋势吗?

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

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