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

wen 开源项目 3

本文目录导读:

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

  1. 核心定义
  2. 代码示例(使用 StatsBomb 免费开源数据)
  3. 更标准的开源工具:socceractionkloppy
  4. 如果使用 Understat(开源 API)
  5. 统计建议
  6. 开源数据源推荐

在足球数据分析中,“禁区内射门次数”是衡量进攻质量的核心指标(常称为 xG 的辅助数据),要统计开源项目(如 StatsBomb、Understat 或通过 API 爬取的 Wyscout 数据)中的禁区内射门次数,通常需要结合事件数据坐标进行计算。

以下是通过开源框架(如 Python 的 statsbombpy)统计禁区内射门次数的具体逻辑和代码示例:

核心定义

首先需要定义“禁区”的坐标范围,虽然不同数据源坐标系不同(如 StatsBomb 使用 120x80,Wyscout 使用 100x100),但逻辑一致:

  • X 坐标:球门位于 X 轴 100(或 120)处。
  • Y 坐标:球场宽度(通常为 80 或 100)。
  • 禁区边界
    • 距离底线约 16.5 米(18 码)。
    • 在数据坐标系中,通常对应 X 坐标 > 102(StatsBomb) 或 X 坐标 > 83(部分 100 坐标系)。
    • Y 坐标限制在禁区宽度内(通常为宽度的 1/3 左右,即 Y > 20 且 Y < 60,具体依坐标系而定)。

代码示例(使用 StatsBomb 免费开源数据)

StatsBomb 提供了官方的 statsbombpy 包,数据是免费的(需遵守开源许可)。

import pandas as pd
from statsbombpy import sb
# 加载比赛数据(以梅西某场比赛为例,这里使用公开的英超或世界杯数据)
# 获取比赛的 ID 列表(需自行查找)
competition_id = 43  # 示例:世界杯
season_id = 106      # 示例:2022 赛季
matches = sb.matches(competition_id=competition_id, season_id=season_id)
match_id = matches['match_id'].iloc[0]  # 取第一场比赛
# 获取事件数据
events = sb.events(match_id=match_id)
# 筛选射门事件(shot)
shots = events[events['type'] == 'Shot']
# 处理缺失坐标
shots = shots.dropna(subset=['location'])
# 解析坐标
shots['x'] = shots['location'].apply(lambda loc: loc[0])
shots['y'] = shots['location'].apply(lambda loc: loc[1])
# 定义禁区范围(StatsBomb:球场 120x80)
# 禁区 X > 102 (距离球门线 18 码 = 约 16.5m,120 单位中约为 18/105*120 ≈ 20.5,因此球门线是 120,禁区线是 120 - 20.5 = 99.5?需要根据实际来源微调)
# 常见简化处理:X > 105 且 Y 在 15 到 65 之间。
# 注意:StatsBomb 球门位于 X=120,因此越靠近球门 X 越大。
in_box = (shots['x'] >= 102) & (shots['y'] >= 18) & (shots['y'] <= 62)
# 统计
box_shots = shots[in_box]
box_shot_count = len(box_shots)
print(f"禁区内射门次数: {box_shot_count}")
print("禁区内射门占总射门比例: {:.2f}%".format(box_shot_count / len(shots) * 100))

更标准的开源工具:socceractionkloppy

为了更严谨,建议使用 kloppy 库,它能统一处理 StatsBomb、Wyscout、Sportec 等格式,并内置了球场几何转换。

from kloppy import statsbomb
from kloppy.domain import Point, Period
# 加载数据(需要本地文件路径)
dataset = statsbomb.load(
    event_data="events.json",
    lineup_data="lineups.json",
    # ... 具体 API
)
# 获取所有射门
shots = dataset.events.filter_types("SHOT")
# 检查坐标是否在禁区内(kloppy 的坐标统一为 0~1 的归一化坐标系)
# 禁区:x > 0.85, y 在 0.2 到 0.8 之间(近似)
in_box = 0
for shot in shots:
    x = shot.coordinates.x  # 0~1 的百分制
    y = shot.coordinates.y
    if x > 0.85 and 0.2 < y < 0.8:
        in_box += 1

如果使用 Understat(开源 API)

Understat 提供免费 API 但官方限制访问,可用 understatapi 爬取,但该库非官方且可能失效,通常使用 requests + 解析 xy 坐标(Understat 坐标系为 100x100,但数据单位是百分比)。

import requests
from bs4 import BeautifulSoup
import json
# 获取比赛数据的 URL(示例)
url = "https://understat.com/match/4040"
headers = {'User-Agent': 'Mozilla/5.0'}
res = requests.get(url, headers=headers)
soup = BeautifulSoup(res.text, 'lxml')
# 在脚本中找到 JSON 数据,解析 shot 数据
# 标准逻辑:读取 coordinates 字段中的 x, y

统计建议

  • 统一坐标系:务必明确数据源坐标系(120x80 或 100x100),并正确换算。
  • 射门是否包括被阻挡:射门”包括进球、射正、射偏和被挡。
  • 禁区定义:根据国际足联规则,禁区为距门柱 16.5 米,但统计时有的用“大禁区”(包括弧顶)或“小禁区”(点球点附近),开源数据一般指 大禁区

开源数据源推荐

数据源 覆盖范围 免费性 坐标系
StatsBomb (Free) 欧洲杯、世界杯等 完全免费 120x80
Understat 欧洲五大联赛 免费(爬虫) 100x100
WhoScored / Sofascore 赛事丰富 付费,但有爬虫接口 100x100

最简单的开源方式是使用 StatsBomb 数据集(如 FA Women‘s Super League 或世界杯),因为它提供了官方 Python 包,无需处理复杂的数据结构,如果你需要现成的统计结果(而不是代码),可去 FBref.comUnderstat 的公开页面查询,但这些不是“开源项目”,而是免费网站。

如果你需要针对特定球队或特定赛季的排行榜,我可以帮你用 statsbombpy 拉取数据生成统计。

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