mcpField
N
nutmeg-wrangle

nutmeg-wrangle

github.com/withqwerty数据与数据库55164 次安装今天更新
代码仓库

关于 nutmeg-wrangle

nutmeg-wrangle 是处理足球数据的技能,涵盖筛选、合并、重塑、格式转换和数据校验,并提供坐标变换及大数据处理方法。指导会根据用户使用的语言和工具调整。

主要功能

  1. 01指导按事件和区域筛选
  2. 02说明数据集合并与重塑
  3. 03涵盖不同提供方的坐标变换
  4. 04建议大数据处理方法
  5. 05列出数据质量检查项

适用场景

  1. 01按类型或比赛状态筛选事件
  2. 02将事件与阵容或 xG 合并
  3. 03合并不同来源前转换坐标
  4. 04校验并重塑赛季数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/withqwerty/nutmeg --skill nutmeg-wrangle

安装后在 Claude Code 中输入/nutmeg-wrangle确认已加载。

详细介绍

数据整理

帮助用户高效处理足球数据。此技能介绍处理数据的方法,并根据用户的语言和工具进行调整。

准确性

在回答任何关于特定数据提供方的事实(ID、端点、架构、坐标、速率限制)的问题前,先阅读并遵循 ${CLAUDE_PLUGIN_ROOT}/docs/accuracy-guardrail.md。始终使用 search_docs,切勿根据训练数据猜测。

首先:检查配置

读取 .nutmeg.user.md。如果文件不存在,则使用合理的默认设置(Python 和 pandas,具有中级水平),并在最后建议运行 /nutmeg setup。根据用户的配置选择语言和技术栈。

核心操作

坐标转换

足球数据坐标因提供方而异。合并数据前,务必先核实并转换坐标。

使用 search_docs(query="coordinate system", provider="[provider]") 查询各提供方的原点、范围和 y 轴方向。不要凭记忆编写转换公式:各提供方的 y=0 所在边线不同,因此仅重新缩放的公式可能会镜像球场。

  • Python:优先使用 kloppy 的 .transform() 或 mplsoccer 的 Standardizer,它们能处理各提供方的方向定义。
  • 手动编写转换:根据查到的定义推导公式,然后进行测试。开球位置应落在中圈中心,球队的射门应集中在其进攻方向的球门附近。
筛选事件

足球事件数据的常见筛选模式:

按事件类型:

  • 射门:筛选射门、射偏、进球或被扑救等事件类型
  • 进攻三区传球:筛选位于提供方 x 轴范围最后三分之一内的传球(对于 0-100 的球场,x > 66.7)
  • 防守动作:抢断 + 拦截,并根据定义加入犯规、争抢、封堵或球权恢复(请明确说明采用的定义)

按比赛状态:

  • 仅开放式进攻:排除定位球(角球、任意球、界外球、点球)
  • 上半场与下半场:使用 periodId 或时间戳
  • 比分状态:跟踪实时比分,以筛选“领先时”或“落后时”的数据

按区域:

  • 禁区内动作:使用 search_docs(query="pitch zones", provider="[provider]") 查询提供方的禁区边界;这些边界在标准化球场上为近似值
  • 高位压迫:筛选发生在对手防守三区内的动作(提供方 x 轴范围的最后三分之一)
合并数据集

足球数据中的常见合并方式:

合并数据键说明
事件 + 阵容player_id + match_id获取每个事件对应的球员姓名和位置
事件 + xGmatch_id + 事件序列将 xG 匹配到具体射门
多个提供方Reep ID将各提供方的 (provider, namespace, id) 映射到 Reep ID,然后按 Reep ID 合并
赛季数据 + Elodate合并比赛当时的 Elo 评级

**合并不同提供方的数据:**通过 Reep Register ID 合并,而不是通过名称(参见 ${CLAUDE_PLUGIN_ROOT}/docs/entity-resolution-routing.md)。不同提供方使用的名称可能不同(“Man City” / “Manchester City”),不同球员也可能同名,而且模糊名称匹配可能静默失败。

  • 使用 Reep 工具(resolve、translate)或 resolve_entity 查询 ID,或者查询 Reep 发布版 DuckDB 进行批量合并。
  • 保留无法解析的行,并报告各提供方未解析的行数。绝不要静默丢弃这些行。
  • 只有在 Reep 未涵盖相关实体时,才将手动创建的名称映射作为最后手段;并将这些行标记为按名称匹配,以便用户检查。
重塑数据

常见的数据重塑操作:

  • **宽表转长表:**将赛季统计表(每项统计各占一列)转换为整洁格式(每支球队的每项统计各占一行)
  • **事件转控球链:**将同一球队连续发生的事件分组为控球序列
  • **比赛级数据转赛季汇总:**按球队分组,计算每场比赛数值的总和或平均值
  • **球员-比赛数据转球员-赛季数据:**跨比赛汇总,并按上场分钟数加权
处理大型数据集

一个完整赛季的赛事数据可能达到数百 MB,追踪数据则可能大得多。可采用以下策略:

Python:

  • 处理大型表格时使用 polars 替代 pandas;它通常快得多
  • 在循环中逐场处理,不要将所有数据都加载到内存中
  • 使用 DuckDB 对 Parquet 文件执行 SQL 查询,无需将数据加载到内存中

JavaScript/TypeScript:

  • 使用 readline 或 JSONStream 流式读取 JSON 文件
  • 使用 SQLite(better-sqlite3)进行本地查询
  • 使用工作线程并行处理文件

R:

  • 处理大型数据集时使用 data.table 替代 tidyverse
  • 使用 Arrow/Parquet 进行内存外处理
数据质量检查

完成数据整理后,务必进行验证:

检查项检查内容
赛事计数将每场比赛与同一数据集中的其他比赛进行比较。典型计数取决于数据提供方,因此应标记异常值,而不是使用固定数值
坐标范围应处于数据提供方预期的范围内
缺失的球员 ID部分事件缺少球员归属信息(如球出界等)
重复事件同一个 event_id 出现两次
时间间隔一场比赛的事件时间戳之间存在较大间隔
球队归属确认主队/客队归属一致
格式转换
来源目标工具/方法
JSON 事件DataFrame使用 pandas/polars 的 read_json 或手动解析
CSVParquetdf.write_parquet()(polars)或 df.to_parquet()(pandas)
数据提供方格式kloppy 模型在 Python 中使用 kloppy.load_{provider}()
kloppy 模型DataFramedataset.to_df()
任意格式SQLite加载到 SQLite 中以便临时查询

评论

支持 Markdown