开源项目统计禁区内射门次数对比?

wen 开源项目 4

本文目录导读:

开源项目统计禁区内射门次数对比?

  1. 核心逻辑定义
  2. Python 代码示例(使用 mplsoccer 和 pandas)
  3. 更专业的开源库:kloppy
  4. 其他数据源对比(如 Wyscout)
  5. 可视化对比(进阶)
  6. 总结要点

这是一个在足球数据分析中非常经典且常见的需求,在开源项目中,“禁区” 通常被定义为 “罚球区”(Penalty Area),而 “射门” 则通常特指 “尝试射门”(Shots Attempts,包含被扑出、被挡出、射偏和进球)

要在开源项目中统计并进行对比(通常是主队 vs 客队,或两支特定球队),逻辑通常分为 数据获取、事件过滤、空间计算 三个步骤。

以下是基于主流开源足球数据分析框架(如 StatsBombRkloppySofaPymplsoccer 等 Python 库)的通用实现逻辑和方法说明:

核心逻辑定义

  • 禁区范围:通常定义为球场坐标系中的矩形区域。

    • 标准坐标(如 StatsBomb 数据,0-120 x 0-80):
      • X轴:从底线起(通常是 102 到 120 之间,取决于进攻方向)。
      • Y轴:宽度范围通常是 18 码(约 16.5 米),在标准化坐标中通常是 1862 之间(即禁区宽度 44 码的一部分,更精确的坐标需要换算)。
      • 简化判断法:大多数库内置了 pitch 对象,可以直接用 pitch. PenaltyArea 进行空间判断。
  • 事件类型Shot(射门)事件。

  • 触球位置:射门事件记录中的 location(X,Y)坐标。

Python 代码示例(使用 mplsoccer 和 pandas)

以下是一个使用 mplsoccer 分析 StatsBomb 免费数据的示例,用于统计主队和客队的禁区内外射门次数。

import pandas as pd
from mplsoccer.pitch import Pitch
from mplsoccer.statsbomb import StatsBomb
# 1. 加载数据(以 StatsBomb 欧冠决赛为例)
sb = StatsBomb()
# 获取比赛ID:15946 (巴萨vs尤文)
events = sb.competition_and_match_id_to_df(competition_id=16, season_id=27, match_id=15946)
# 2. 筛选射门事件
shots = events[events['type'] == 'Shot'].copy()
# 3. 创建球场对象用于空间计算
pitch = Pitch(pitch_type='statsbomb', pitch_color='white', line_color='black')
# 4. 定义函数判断是否在禁区内
def is_penalty_area(row):
    # 获取射门坐标
    x = row['x']
    y = row['y']
    if pd.isna(x) or pd.isna(y):
        return False
    # 调用 mplsoccer 的几何判断方法
    # 注意:这里需要根据进攻方向标准化坐标,StatsBomb 数据通常已标准化为进攻方向朝右(x=120 是对方球门)
    # 判断矩形范围:x 坐标 102 到 120,y 坐标 18 到 62
    return (x >= 102) & (x <= 120) & (y >= 18) & (y <= 62)
# 更准确的判断(考虑进攻方向变化,使用 mplsoccer 的 find_geometric_shapes):
# 但为了简洁,假设所有射门都在进攻半场(x>60),且方向已标准化
shots['in_area'] = shots.apply(lambda row: (row['x'] >= 102) & (row['y'] >= 18) & (row['y'] <= 62), axis=1)
# 5. 区分主客队
# 通常事件表里有 'team' 列
home_team = shots['team'].unique()[0] # 假设第一支是主队
away_team = shots['team'].unique()[1]
home_shots = shots[shots['team'] == home_team]
away_shots = shots[shots['team'] == away_team]
# 6. 统计对比
summary = pd.DataFrame({
    'Team': [home_team, away_team],
    'Total Shots': [len(home_shots), len(away_shots)],
    'Inside Box': [home_shots['in_area'].sum(), away_shots['in_area'].sum()],
    'Outside Box': [len(home_shots) - home_shots['in_area'].sum(), 
                    len(away_shots) - away_shots['in_area'].sum()]
})
print(summary)

更专业的开源库:kloppy

kloppy 是一个标准化的足球数据解析库,它支持多种数据源,并且集成了球场几何计算,可以非常方便地判断事件位置。

from kloppy import statsbomb, helpers
from kloppy.domain import Ground
# 加载数据
dataset = statsbomb.load(...)  # 加载你的数据
# 筛选事件
shots = dataset.events.filter('shot')
# 使用 kloppy 的 PitchDimensions 判断
# kloppy 有内置的 `is_in_penalty_area` 功能
home_team = dataset.metadata.teams[0]
away_team = dataset.metadata.teams[1]
stats = {}
for team in [home_team, away_team]:
    team_shots = shots.filter(team=team)
    in_box = 0
    out_box = 0
    for event in team_shots:
        # 获取球位置
        ball_x, ball_y = event.ball.coordinates
        # 调用几何库判断
        if helpers.is_in_penalty_area(ball_x, ball_y, direction='right'): # 方向根据数据源设定
            in_box += 1
        else:
            out_box += 1
    stats[team.name] = {'in': in_box, 'out': out_box}
print(stats)

其他数据源对比(如 Wyscout)

如果你使用的是 Wyscout 数据(通常通过 SofaPy 或自建爬虫),其坐标系与 StatsBomb 不同(X轴 0-100,Y轴 0-100),判断逻辑需要按比例换算:

  • Wyscout 禁区范围(进攻方向朝左或右):
    • X轴:小于 5(如果进攻方向朝左)或 大于 5(如果朝右)。
    • Y轴:55(因为 Wyscout 的 Y 轴是 0-100,18 码约等于 16.5 的单位)。

可视化对比(进阶)

如果不仅仅要统计数字,还要可视化展示射门位置,可以使用 mplsoccer 绘制分面图(Facet Grid)来对比禁区内外的分布:

# 可视化代码片段
fig, axes = pitch.grid(nrows=2, ncols=1, grid_height=0.8, endnote_height=0.03, title_height=0.08, axis=False)
# 主队
pitch.scatter(home_shots['x'], home_shots['y'], ax=axes['pitch'][0], c='blue', label='Home')
# 客队
pitch.scatter(away_shots['x'], away_shots['y'], ax=axes['pitch'][1], c='red', label='Away')
# 添加禁区线条
for ax in axes['pitch']:
    pitch.draw(ax=ax)
plt.show()

总结要点

  1. 核心:关键在于 “过滤条件”——射门事件 + 空间坐标判断
  2. 标准差异:不同数据源的坐标系(StatsBomb 120x80,Wyscout 100x100)会影响禁区的坐标阈值
  3. 常用工具
    • mplsoccer(可视化 + 简单的坐标判断)
    • kloppy(标准化数据解析,自带空间几何判断,推荐用于严格的数据分析)
    • pandas(数据处理与聚合)

如果你需要针对特定的公开数据集(Kaggle 上的 CSV 文件)写具体代码,也可以提供数据字段名(比如列名是 XY,还是 location_x),我可以帮你写出完整的对比统计脚本。

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