本文目录导读:

这个问题非常经典,而且很有实战价值。“反击” 在足球数据里的定义比较模糊(通常指从夺回球权后,在特定时间(如15秒内)和特定推进方式(纵向传递或带球)下完成的射门或进入对方30米区域)。
要衡量“哪队更高效”,不能只看反击进球数,因为进球多可能只是因为反击总次数多。真正的“高效”应该看转化率,即每次反击创造射门/进球的机会权重。
下面我提供一个Python实用脚本,它能帮你处理常见的比赛事件数据(如 .csv 或结构化数据),并输出反击效率排行榜。
核心逻辑(为什么这么算)
脚本会计算三个维度的效率指标,避免被“绝对数量”迷惑:
- 反击破门率:反击进球数 / 反击总次数(最直观的“把握度”)。
- 反击射正率:反击射正数 / 反击射门数(衡量反击质量)。
- 综合反击指数(加权评分):将“进球”与“射门”结合(进球权重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))
脚本使用说明(重点)
-
数据要求:
- 用
pandas读取数据。 - 每一行代表一个事件,必须包含
team(球队)和event_type(事件类型)。 - 关键点:事件类型中必须能识别出
counter(反击)、shot(射门)、goal(进球)。 - 如果有后续字段(如
outcome),可以更精细区分射正。
- 用
-
核心输出指标:
- Conversion_Rate(破门转化率):每次反击进球的概率。
- Shot_Accuracy(射正率):反击中射门射正的比例。
- Efficiency_Score(综合评分):结合进球和射正的加权分数,满分100。
-
如何判断“谁更高效”:
- 看效率评分:评分最高者综合最强。
- 如果评分接近:看
Conversion_Rate(进球转化),进球转化率高的更致命。
进阶优化提示(如果数据更详细)
如果数据来源更专业(如 StatsBomb 或 Wyscout),脚本可以增加以下优化:
- 引入“时间窗口”:从夺回球权到射门少于 15 秒,且推进距离超过 30 米才算“反击”。
- 考虑“反击发起点”:己方半场发起比对方半场发起更难,效率权重应更高。
- 加入“xG”数据:用
反击期望进球数除以实际反击次数,得出“每次反击创造机会价值”。
如果你有具体的比赛数据文件(比如从 Understat 或 Fbref 下载的),可以发给我数据格式,我可以帮你把脚本调整为适配特定列名的版本。