实用脚本统计反击次数哪队更高效?

wen 实用脚本 1

本文目录导读:

实用脚本统计反击次数哪队更高效?

  1. 核心逻辑(为什么这么算)
  2. Python 脚本:counter_attack_efficiency.py
  3. 脚本使用说明(重点)
  4. 进阶优化提示(如果数据更详细)

这个问题非常经典,而且很有实战价值。“反击” 在足球数据里的定义比较模糊(通常指从夺回球权后,在特定时间(如15秒内)和特定推进方式(纵向传递或带球)下完成的射门或进入对方30米区域)。

要衡量“哪队更高效”,不能只看反击进球数,因为进球多可能只是因为反击总次数多。真正的“高效”应该看转化率,即每次反击创造射门/进球的机会权重

下面我提供一个Python实用脚本,它能帮你处理常见的比赛事件数据(如 .csv 或结构化数据),并输出反击效率排行榜


核心逻辑(为什么这么算)

脚本会计算三个维度的效率指标,避免被“绝对数量”迷惑:

  1. 反击破门率:反击进球数 / 反击总次数(最直观的“把握度”)。
  2. 反击射正率:反击射正数 / 反击射门数(衡量反击质量)。
  3. 综合反击指数(加权评分):将“进球”与“射门”结合(进球权重0.7,射正权重0.3),消除单纯靠“蒙一脚”带来的误差。

Python 脚本:counter_attack_efficiency.py

import pandas as pd
import numpy as np
def calculate_counter_efficiency(data_path):
    """
    计算各球队的反击效率指标
    参数:
    data_path: CSV 文件路径
    数据列假设:
    - team: 球队名称
    - event_type: 事件类型 (必须包含 'counter_attack', 'counter_shoot', 'counter_shot_on_target', 'counter_goal')
    - outcome: 结果 (仅用于射门)
    返回:
    DataFrame: 包含各队反击效率的排名表
    """
    # 读取数据
    df = pd.read_csv(data_path)
    # --- 1. 数据预处理:确保所有反击事件都有标记 ---
    # 假设原始数据中凡是反击事件,在 'event_type' 列会以 'counter_' 开头
    # 如果数据只有一种“反击导致射门”的记录,需要额外拆分,这里提供通用处理:
    # 确保有射门结果列,用于区分射正与否
    if 'outcome' not in df.columns:
        # 如果没有结果列,假设 'event_type' 已经区分了 goal 和 shot_on_target
        outcomes = df['event_type'].str.contains('goal').map({True: 'goal', False: 'other'})
        df['outcome'] = np.where(df['event_type'].str.contains('shot_on_target'), 'on_target',
                          np.where(df['event_type'].str.contains('goal'), 'goal', 'other'))
    # --- 2. 构建反击事件计数表 ---
    # 我们需要统计每个队三类数据:
    # a. 反击总次数 (counter attacks started)
    # b. 反击射门数 (including goals & blocks)
    # c. 反击射正数 (on target, excluding blocked)
    # d. 反击进球数 (goals)
    # 创建基础统计容器
    team_stats = {}
    # 遍历每个球队
    for team in df['team'].unique():
        team_df = df[df['team'] == team]
        # 反击总次数:统计所有包含 'counter' 且是进攻发起的事件
        # 假设 event_type 有 'counter_start'(夺回球权)
        # 如果数据没有单独的 start 标记,用射门+被抢断等代替,这里简化处理:
        # 方案:统计所有 event_type 包含 'counter' 的行数(如果一条数据代表一次反击发起)
        total_counters = len(team_df[team_df['event_type'].str.contains('counter', case=False)])
        # 如果统计口径是“每次反击对应一条射门记录”,则 total_counters 应改为射门次数
        # 这里假设数据里既有“发起”也有“终结”,我们需要筛选出“终结”事件
        # 更准确的统计:通常一场比赛的反击次数 = 所有反击射门 + 反击未形成射门的次数
        # 由于后者数据难以获取,我们退而求其次:统计“反击产生射门”的次数作为分母
        # 筛选出所有反击射门事件(包括进球)
        shots = team_df[team_df['event_type'].str.contains('counter', case=False) & 
                        (team_df['event_type'].str.contains('shot', case=False) | 
                         team_df['event_type'].str.contains('goal', case=False))]
        # 反击射门次数
        total_shots = len(shots)
        # 反击射正数(包括进球,因为进球必然射正)
        on_target = 0
        goals = 0
        for _, row in shots.iterrows():
            event = row['event_type']
            outcome = row.get('outcome', '')
            # 如果结果是进球
            if ('goal' in event) or (outcome == 'goal'):
                goals += 1
                on_target += 1  # 进球必射正
            elif ('on_target' in event) or (outcome == 'on_target'):
                on_target += 1
            # 如果被门柱或扑出未算射正,则不增加
        # 存储结果
        team_stats[team] = {
            'Counter_Attacks': total_counters,  # 反击次数
            'Shots': total_shots,            # 反击射门
            'On_Target': on_target,          # 射正
            'Goals': goals                   # 进球
        }
    # --- 3. 计算效率指标 ---
    result_df = pd.DataFrame(team_stats).T
    result_df.reset_index(inplace=True)
    result_df.rename(columns={'index': 'Team'}, inplace=True)
    # 避免除零错误
    result_df.replace(0, np.nan, inplace=True)
    # 反击破门率(每次反击进球的概率)
    result_df['Conversion_Rate'] = result_df['Goals'] / result_df['Counter_Attacks']
    # 反击射正率(每次射门射正的概率)
    result_df['Shot_Accuracy'] = result_df['On_Target'] / result_df['Shots']
    # 综合效率评分 (0-100)
    # 权重:进球权重 0.6,射正权重 0.4(因为射正代表威胁更大)
    # 标准化处理:除以全联盟最大值,让分数集中在0-100区间
    max_goals = result_df['Goals'].max()
    max_shots_on_target = result_df['On_Target'].max()
    if max_goals > 0 and max_shots_on_target > 0:
        result_df['Efficiency_Score'] = (
            (result_df['Goals'] / max_goals) * 60 +
            (result_df['On_Target'] / max_shots_on_target) * 40
        )
    else:
        result_df['Efficiency_Score'] = 0
    # 排序输出(按综合效率降序)
    result_df = result_df.sort_values('Efficiency_Score', ascending=False)
    # 填充 NaN
    result_df = result_df.fillna(0)
    # 格式化为百分比
    result_df['Conversion_Rate'] = result_df['Conversion_Rate'] * 100
    result_df['Shot_Accuracy'] = result_df['Shot_Accuracy'] * 100
    return result_df
# --- 使用示例 ---
if __name__ == "__main__":
    # 假设你的数据文件在 data.csv
    # 格式示例:
    # team,event_type,outcome
    # TeamA,counter_start,NA
    # TeamA,counter_shot,on_target
    # TeamA,counter_goal,goal
    # TeamB,counter_start,NA
    # TeamB,counter_shot,off_target
    # 这里生成模拟数据用于演示
    import io
    sample_data = """team,event_type,outcome
利物浦,counter_start,NA
利物浦,counter_shot,on_target
利物浦,counter_goal,goal
利物浦,counter_shots,on_target
曼城,counter_start,NA
曼城,counter_shot,off_target
曼城,counter_start,NA
曼城,counter_goal,goal
阿森纳,counter_start,NA
阿森纳,counter_shot,on_target
阿森纳,counter_start,NA
阿森纳,counter_start,NA
"""
    # 写入临时文件并计算
    with open('counter_demo.csv', 'w') as f:
        f.write(sample_data)
    results = calculate_counter_efficiency('counter_demo.csv')
    print("反击效率排行榜:")
    print(results.to_string(index=False))

脚本使用说明(重点)

  1. 数据要求

    • pandas 读取数据。
    • 每一行代表一个事件,必须包含 team(球队)和 event_type(事件类型)。
    • 关键点:事件类型中必须能识别出 counter(反击)、shot(射门)、goal(进球)。
    • 如果有后续字段(如 outcome),可以更精细区分射正。
  2. 核心输出指标

    • Conversion_Rate(破门转化率):每次反击进球的概率。
    • Shot_Accuracy(射正率):反击中射门射正的比例。
    • Efficiency_Score(综合评分):结合进球和射正的加权分数,满分100。
  3. 如何判断“谁更高效”

    • 看效率评分:评分最高者综合最强。
    • 如果评分接近:看 Conversion_Rate(进球转化),进球转化率高的更致命。

进阶优化提示(如果数据更详细)

如果数据来源更专业(如 StatsBomb 或 Wyscout),脚本可以增加以下优化:

  • 引入“时间窗口”:从夺回球权到射门少于 15 秒,且推进距离超过 30 米才算“反击”。
  • 考虑“反击发起点”:己方半场发起比对方半场发起更难,效率权重应更高。
  • 加入“xG”数据:用 反击期望进球数 除以 实际反击次数,得出“每次反击创造机会价值”。

如果你有具体的比赛数据文件(比如从 UnderstatFbref 下载的),可以发给我数据格式,我可以帮你把脚本调整为适配特定列名的版本。

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