根据Python案例,进攻三区传球成功率?

wen python案例 2

本文目录导读:

根据Python案例,进攻三区传球成功率?

  1. 案例背景
  2. 步骤 1:模拟或读取数据
  3. 步骤 2:定义进攻三区并过滤数据
  4. 步骤 3:计算传球成功率
  5. 步骤 4:进阶分析(可选,增加实战意义)
  6. 步骤 5:可视化(建议)
  7. 可能遇到的常见问题及解决(针对Python案例)

针对你提到的“进攻三区传球成功率”这一数据指标,结合Python的体育数据分析(特别是足球分析)案例,我们可以从数据获取、数据清洗、核心计算逻辑、可视化四个维度来拆解这个案例。

由于你没有提供具体的原始数据格式(例如是来自StatsBomb、WyScout的XML/JSON,或者是手动整理的CSV),我为你构建一个通用的、可运行的Python分析案例,并附带核心代码解释。

案例背景

  • 定义:进攻三区通常指球场上距离对方球门约35-40米以内的区域(即最后1/3场地)。
  • 目标:计算某球员或某支球队在进攻三区内,所有传球的成功率(成功传球次数 / 总传球次数)。
  • 数据字段假设:一个包含每脚传球信息的CSV文件。

步骤 1:模拟或读取数据

假设我们有一个名为 passes.csv 的文件,包含以下列:player_namex(传球起点x坐标)、y(传球起点y坐标)、pass_outcome(传球结果,如 “Successful”, “Unsuccessful”, “Key Pass”)。

import pandas as pd
import numpy as np
# 为了演示,我们创建模拟数据
np.random.seed(42)
data = {
    'player_name': ['Player_A'] * 50 + ['Player_B'] * 50,
    'x': np.random.uniform(70, 105, 100),  # 进攻三区通常在x>66(标准场地105米)
    'y': np.random.uniform(0, 68, 100),
    'pass_outcome': np.random.choice(['Successful', 'Unsuccessful'], 100, p=[0.7, 0.3])
}
df = pd.DataFrame(data)
print(df.head())

步骤 2:定义进攻三区并过滤数据

在标准的105m x 68m足球场中,进攻三区通常定义为 x坐标 >= 70(或根据具体数据源标准,有些定义为最后35米,即 x >= 70)。

# 定义进攻三区的阈值
ATTACKING_THIRD_X = 70  # 假设对方球门在x=105,这边是进攻方向
# 筛选出进攻三区的传球
attacking_third_passes = df[df['x'] >= ATTACKING_THIRD_X].copy()
print(f"进攻三区总传球次数: {len(attacking_third_passes)}")

步骤 3:计算传球成功率

这是核心逻辑:按球员分组,计算每个球员在进攻三区的传球成功率。

# 计算每组的总传球数和成功传球数
grouped = attacking_third_passes.groupby('player_name')['pass_outcome'].agg(
    total_passes='count',
    successful_passes=lambda x: (x == 'Successful').sum()
).reset_index()
# 计算成功率
grouped['success_rate'] = (grouped['successful_passes'] / grouped['total_passes']) * 100
print("\n进攻三区传球成功率统计:")
print(grouped)

输出示例:

   player_name  total_passes  successful_passes  success_rate
0    Player_A            36                 26     72.222222
1    Player_B            34                 24     70.588235

步骤 4:进阶分析(可选,增加实战意义)

在实际的足球分析案例中,仅仅计算“成功/总”是不够的,很多时候需要区分向前的传球或者关键传球

1 计算“向前传球成功率”

假设数据中有 end_x(传球终点x坐标),向前传递定义为 end_x > x

# 假设我们添加了终点坐标
df['end_x'] = df['x'] + np.random.uniform(-5, 15, 100)  # 模拟终点
# 过滤进攻三区的向前传球
attacking_third_passes['is_forward'] = attacking_third_passes['end_x'] > attacking_third_passes['x']
forward_passes = attacking_third_passes[attacking_third_passes['is_forward']]
# 计算向前传球成功率 (分组计算)
forward_grouped = forward_passes.groupby('player_name')['pass_outcome'].agg(
    forward_total='count',
    forward_success=lambda x: (x == 'Successful').sum()
)
forward_grouped['forward_success_rate'] = (forward_grouped['forward_success'] / forward_grouped['forward_total']) * 100
print("\n进攻三区向前传球成功率:")
print(forward_grouped)

步骤 5:可视化(建议)

使用 matplotlibseaborn 绘制柱状图对比。

import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
plt.bar(grouped['player_name'], grouped['success_rate'], color=['skyblue', 'lightcoral'])
plt.ylabel('Pass Success Rate (%)')'Attacking Third Pass Success Rate Comparison')
plt.ylim(0, 100)
for index, value in enumerate(grouped['success_rate']):
    plt.text(index, value + 1, f'{value:.1f}%', ha='center', va='bottom')
plt.show()

可能遇到的常见问题及解决(针对Python案例)

  1. 数据粒度问题
    • 问题:如果数据是“逐场比赛”的,需要按 match_id 分组后再汇总,否则不同比赛场次权重不一。
    • 解决:在 groupby 中加入 match_id,或者先按比赛算率,再取平均。
  2. 进攻三区定义不一致
    • 问题:不同数据源(如Opta、StatsBomb)对“区域”的定义不同(有的按等距1/3,有的按事件位置)。
    • 解决:始终硬编码明确的x坐标阈值(如 x > 70),并在文档中注明。
  3. 传球结果分类
    • 问题pass_outcome 字段可能有多种值,如 “Key Pass”、“Assist”、“Offside Pass”、“Blocked”,哪些算“不成功”?
    • 解决:定义清晰的规则,成功”指球到队友脚下且未被拦截/解围。 x in [‘Successful’, ‘Key Pass’, ‘Assist’]

这个Python案例的核心逻辑是:

  1. 过滤:根据 x 坐标提取进攻三区事件。
  2. 聚合:按 player_name 分组,计数 count 和条件计数 sum(condition)
  3. 计算success_rate = sum(成功) / count(总) * 100

如果你有具体的原始数据文件(比如Wyscout或StatsBomb的JSON格式),我可以帮你写更具体的解析代码。

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