python案例如何量化防守反击的效率值?

wen python案例 1

本文目录导读:

python案例如何量化防守反击的效率值?

  1. 第一步:定义“防守反击”的判定规则(业务逻辑)
  2. 第二步:构建Python量化模型
  3. 结合你的实际情况,有三种算法选择
  4. 最后:进阶建议(让效率值更有说服力)

量化防守反击的效率值是足球数据分析(或其他对抗性运动)中的一个热门且复杂的课题,它不能仅仅用“进球数”来定义,因为防守反击的起点是“夺回球权”,终点是“射门得分”。

要在一个Python案例中量化它,我们需要构建一个复合指标体系,我会提供一个完整的、结构化的Python分析框架,你只需将数据源替换为你自己的事件数据(如StatsBomb、Wyscout或自爬数据)即可。

以下是完整方案:

第一步:定义“防守反击”的判定规则(业务逻辑)

在写代码前,先界定什么是反击,通常需满足三个条件,缺一不可:

  1. 发起阶段(夺回球权):在本方半场或中场区域(防守三区及中场)获得球权。
  2. 过程阶段(快速推进):在极短时间内(如< 15秒)将球推进到前场(进攻三区)。
  3. 结果阶段(创造威胁):最终形成射门进入禁区绝佳机会

第二步:构建Python量化模型

以下代码展示了如何计算“每次反击预期进球值(xG)”“反击效率指数(CEI)”

核心依赖库

import pandas as pd
import numpy as np

阶段 1:数据准备与特征工程

假设你的数据表结构如下(列名需匹配你的实际数据,这里用虚拟列名):

  • match_id, event_id, team
  • event_type ('TakeOn', 'Pass', 'Shot', 'Interception', 'Tackle'...)
  • start_x, start_y (进攻方向从左至右,0-100)
  • end_x, end_y
  • time_seconds (比赛进行时间,秒)
  • is_win (该事件是否赢得球权)
# 示例数据加载(替换为你的真实数据)
df = pd.read_csv('your_match_events.csv')
# 将坐标标准化为0-100
pitch_length = 105  # 米
pitch_width = 68
def normalize_coord(coord, max_dim):
    return (coord / max_dim) * 100
# 计算事件距离球门的距离(假设进攻方向向右)
df['dist_to_goal'] = np.sqrt((100 - df['start_x'])**2 + (50 - df['start_y'])**2)
df['time_after_win'] = df.groupby('team').cumsum().cumcount() # 占位,实际需按轮次匹配

阶段 2:核心函数 - 识别并提取反击序列

这是最关键的一步,利用窗口函数锁定“夺回球权”后15秒内的连续事件。

def find_counter_attacks(df):
    """
    识别所有防守反击序列。
    返回一个包含每个反击事件的DataFrame,附带上下文特征。
    """
    counter_attacks = []
    # 1. 标记球权转换点(从对方变为我方,且通过防守动作获得)
    df['possession_change'] = (df['team'] != df['team'].shift(1)) & (df['is_win'] == True)
    # 2. 按队伍分组,遍历每个事件
    for team, group in df.groupby('team'):
        group = group.sort_values('time_seconds').reset_index(drop=True)
        possession_sequence = []  # 存储当前球队的单次进攻序列
        for idx, row in group.iterrows():
            if row['possession_change']:  # 新进攻开始
                # --- 反击判定条件 ---
                # 条件 A:在本方40米区域内夺回球权
                in_defensive_zone = row['start_x'] < 40
                # 条件 B:该序列持续时间短(此逻辑在下方扩展)
                if in_defensive_zone:
                    # 重置序列,开始收集
                    possession_sequence = [row]
                else:
                    possession_sequence = []
            else:
                # 如果当前序列非空,继续添加事件
                if possession_sequence:
                    possession_sequence.append(row)
            # --- 终止并评估序列 ---
            # 如果序列以射门结束,或者超过了15秒,则判定结束
            if possession_sequence and (row['event_type'] == 'Shot' or 
                                        (row['time_seconds'] - possession_sequence[0]['time_seconds'] > 15)):
                # 计算序列总时间
                seq_time = row['time_seconds'] - possession_sequence[0]['time_seconds']
                # 条件 B校验:必须小于等于15秒
                if 0 < seq_time <= 15 and possession_sequence[0]['start_x'] < 40:
                    # 提取序列信息
                    seq_df = pd.DataFrame(possession_sequence)
                    # 计算该反击的推进距离
                    final_x = seq_df.iloc[-1]['end_x'] if seq_df.iloc[-1]['event_type'] != 'Shot' else seq_df.iloc[-1]['start_x']
                    progress = final_x - possession_sequence[0]['start_x']
                    # 判断是否进入进攻三区
                    reached_final_third = final_x > 66
                    counter_attacks.append({
                        'team': team,
                        'start_time': possession_sequence[0]['time_seconds'],
                        'end_time': row['time_seconds'],
                        'duration': seq_time,
                        'start_x': possession_sequence[0]['start_x'],
                        'end_x': final_x,
                        'progress': progress,
                        'events_in_sequence': len(possession_sequence),
                        'ended_with_shot': seq_df.iloc[-1]['event_type'] == 'Shot',
                        'reached_final_third': reached_final_third,
                        'xG_of_shot': seq_df.iloc[-1].get('xG', 0) if seq_df.iloc[-1]['event_type'] == 'Shot' else 0
                    })
                # 清空序列,继续寻找下一次球权转换
                possession_sequence = []
    return pd.DataFrame(counter_attacks)

阶段 3:计算效率指标(核心输出)

基于提取出的反击数据集,计算以下核心KPI:

def calculate_efficiency_metrics(counter_df):
    """
    计算防守反击效率的核心指标。
    """
    if counter_df.empty:
        return {}
    # 总反击次数
    total_count = len(counter_df)
    # 1. 反击效率指数(CEI):综合得分 = 威胁度 * 速度 * 终结效率
    #    公式:CEI = (0.5 * 完成率) + (0.3 * 速度得分) + (0.2 * 推进深度得分)
    # 完成率:形成射门的比例
    shot_rate = counter_df['ended_with_shot'].mean()
    # 速度得分:反击持续时间越短,得分越高(归一化)
    # 假设最短反击时间为3秒,最长15秒
    speed_score = 1 - ((counter_df['duration'] - 3) / (15 - 3))
    speed_score = speed_score.clip(lower=0, upper=1)
    # 推进深度得分:推进距离占总进攻三区的比例(假设30米)
    progress_score = counter_df['progress'] / 30.0
    progress_score = progress_score.clip(lower=0, upper=1)
    # 综合计算
    counter_df['CEI'] = (0.5 * counter_df['ended_with_shot'].astype(int) + 
                         0.3 * speed_score + 
                         0.2 * progress_score)
    # 2. 每次反击的预期进球产出(xG per counter)
    total_xg = counter_df['xG_of_shot'].sum()
    xg_per_counter = total_xg / total_count
    # 3. 反击转化率(实际进球 / 反击次数),需结合进球数据
    # 假设进球列存在于原数据中,这里用xG替代
    metrics = {
        'total_counter_attacks': total_count,
        'avg_duration': counter_df['duration'].mean(),
        'shot_conversion_rate': shot_rate,
        'xg_per_counter': xg_per_counter,
        'avg_CEI': counter_df['CEI'].mean(),
        'final_third_reach_rate': counter_df['reached_final_third'].mean()
    }
    return metrics
# 运行
counter_attacks_df = find_counter_attacks(df)
metrics = calculate_efficiency_metrics(counter_attacks_df)
print(metrics)

阶段 4:可视化与洞察(附加)

利用matplotlibseaborn绘制散点图直观对比各队效率:

import matplotlib.pyplot as plt
# 按球队聚合
team_metrics = counter_attacks_df.groupby('team').apply(lambda x: calculate_efficiency_metrics(x))
# 可视化:X轴为反击次数,Y轴为平均CEI,气泡大小为总xG
plt.scatter(team_metrics['total_counter_attacks'], 
            team_metrics['avg_CEI'], 
            s=team_metrics['xg_per_counter']*1000, alpha=0.6)
plt.xlabel('Total Counter Attacks')
plt.ylabel('Average Counter Efficiency Index (CEI)')'Defensive Counter-Attack Efficiency Map')
plt.grid(True)
plt.show()

结合你的实际情况,有三种算法选择

算法场景 适用场景 影响因素
基础统计法 拥有基本事件日志 转化率、推进速度
预期进球(xG)加权法 有射门质量数据 位置、角度、防守压力
机器学习(XGBoost)法 大量数据需要自动识别 高维特征(对手阵型、跑位)

进阶建议(让效率值更有说服力)

  1. 对手压力权重:在推进过程中,如果对方有密集防守(防守人数>4),反击的效率应加权打折,可以用计算防守球员距离球的距离来量化。
  2. 有效反击 vs 无效反击:如果反击最终变成了“倒脚回传”导致失去意义,应将其视为失败反击,不计入效率分母。
  3. 纵向推进率:如果反击中向前传球比例低于50%,说明这不是一次合格的反击,应剔除。

请一定要根据你的数据列名调整代码中的字段名(例如将start_x改为x_start,或将时间单位从分钟改为秒),这套框架可以直接在Jupyter Notebook中运行。

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