Skip to main content

Classify and value on-ball football actions using SPADL and VAEP

Project description

Silly Kicks

The Modern SPADL Analyst vs The Chief SPADL Evaluator & Classifier Comic by NanoBanana — inspired by Monty Python's Ministry of Silly Walks

CI

The Ministry requires that all football actions be properly classified and valued.

silly-kicks is a Python library for objectively quantifying the impact of individual actions performed by football players using event stream data.

It is an independently maintained successor to socceraction, originally developed by Tom Decroos and Pieter Robberechts at KU Leuven. Built under the MIT license with full attribution preserved.

Features

  • SPADL -- Soccer Player Action Description Language: a unified schema for on-ball actions with dedicated DataFrame converters for StatsBomb, Wyscout, Opta, Sportec / IDSSE Bundesliga, Metrica Sports, and PFF FC — plus a kloppy gateway for raw-provider-data consumers (StatsBomb, Sportec, Metrica)
  • Tracking -- 19-column long-form per-frame schema parallel to SPADL, with native adapters for Sportec / IDSSE Bundesliga and PFF FC plus a kloppy gateway for Metrica + SkillCorner. Linkage primitive (link_actions_to_frames + slice_around_event) joins SPADL actions to tracking frames (ADR-004). The action-context tracking-aware feature set ships in silly_kicks.tracking.features (PR-S20, ADR-005): four features (nearest_defender_distance, actor_speed, receiver_zone_density, defenders_in_triangle_to_goal) plus aggregator add_action_context and tracking_default_xfns for HybridVAEP integration. Pre-shot goalkeeper position (PR-S21): four GK features (pre_shot_gk_x, pre_shot_gk_y, pre_shot_gk_distance_to_goal, pre_shot_gk_distance_to_shot) plus aggregator add_pre_shot_gk_position and pre_shot_gk_default_xfns. Pre-shot goalkeeper geometry (PR-S24): two signed-angle features (pre_shot_gk_angle_to_shot_trajectory, pre_shot_gk_angle_off_goal_line) plus aggregator add_pre_shot_gk_angle, pre_shot_gk_angle_default_xfns, and union list pre_shot_gk_full_default_xfns. Events-side add_pre_shot_gk_context gains an optional frames= kwarg that emits six GK columns inline (4 PR-S21 positions + 2 PR-S24 angles). Per-action sync-quality (TF-6, PR-S24): sync_score / add_sync_score / LinkReport.sync_scores() return three aggregations (sync_score_min / _mean / _high_quality_frac). Frame preprocessing (PR-S24, silly_kicks.tracking.preprocess): smooth_frames (Savitzky-Golay or EMA), interpolate_frames (linear gap-fill), derive_velocities (vx/vy/speed via SG-derivative), shared PreprocessConfig dataclass with per-provider defaults from a codegen-from-JSON pipeline. Tracking converters take an optional preprocess: PreprocessConfig | None = None kwarg with auto-promotion to per-provider defaults. Pre-action movement (TF-3, PR-S25): two features (actor_arc_length_pre_window, actor_displacement_pre_window) plus add_actor_pre_window aggregator and actor_pre_window_default_xfns (default xfn list ships arc-length only). Multi-flavor pressure on actor (TF-2, PR-S25): pressure_on_actor(method=...) with three published methodologies (andrienko_oval -- Andrienko et al. 2017 directional oval (default); link_zones -- Link et al. 2016 piecewise zones; bekkers_pi -- Bekkers 2024 Pressing Intensity, BSD-3-Clause UnravelSports port) plus per-method frozen parameter dataclasses (AndrienkoParams / LinkParams / BekkersParams) in silly_kicks.tracking.pressure, add_pressure_on_actor umbrella, and pressure_default_xfns (default xfn list ships exactly one flavor per ADR-005 §8 multi-flavor xfn column-naming convention; column pattern pressure_on_actor__<method>). Atomic-SPADL parity in silly_kicks.atomic.tracking.features.
  • VAEP -- Valuing Actions by Estimating Probabilities: a framework for quantifying the value of individual actions
  • Atomic SPADL -- continuous (non-discretized) action representation

Installation

pip install silly-kicks

Requires Python 3.10 or later.

With optional provider support:

pip install "silly-kicks[kloppy,xgboost]"

Quick Start

import silly_kicks.spadl as spadl

# Convert StatsBomb events to SPADL actions
actions, report = spadl.statsbomb.convert_to_actions(events, home_team_id=123)

# Add human-readable names
actions = spadl.add_names(actions)

VAEP Workflow

The full pipeline: convert provider events to SPADL, train a VAEP model, and rate individual actions.

from silly_kicks.spadl import statsbomb
from silly_kicks.vaep import VAEP

# 1. Convert provider events to SPADL
actions, report = statsbomb.convert_to_actions(
    events_df, home_team_id=home_team_id,
    xy_fidelity_version=2, shot_fidelity_version=2,
)

# 2. Train a VAEP model
model = VAEP(nb_prev_actions=3)
features = model.compute_features(game, actions)
labels = model.compute_labels(game, actions)
model.fit(features, labels, learner="xgboost", random_state=42)

# 3. Rate actions
ratings = model.rate(game, actions)
# Returns DataFrame with offensive_value, defensive_value, vaep_value

Hybrid-VAEP

Standard VAEP includes the action's result (success/fail) as a feature, which creates information leakage. HybridVAEP removes result information from the current action while preserving it for previous actions.

from silly_kicks.vaep import HybridVAEP

# HybridVAEP removes result leakage from current-action features
model = HybridVAEP(nb_prev_actions=3)
# Same fit/rate API as standard VAEP

Multi-Provider Support

All converters share the same output schema, so downstream code works identically regardless of the data provider.

from silly_kicks.spadl import opta, wyscout

actions_opta, _ = opta.convert_to_actions(opta_events, home_team_id)
actions_wyscout, _ = wyscout.convert_to_actions(wyscout_events, home_team_id)

Architecture

Open docs/c4/architecture.html in a browser to explore the C4 architecture diagrams (System Context, Containers).

Attribution

This project incorporates academic methodologies from the soccer-analytics literature. See NOTICE for full bibliographic citations and third-party library acknowledgements.

silly-kicks builds on the foundational research by the KU Leuven Machine Learning Research Group. If you use this library in academic work, please cite the original papers:

@inproceedings{Decroos2019VAEP,
  title     = {Actions Speak Louder than Goals: Valuing Player Actions in Soccer},
  author    = {Tom Decroos and Lotte Bransen and Jan Van Haaren and Jesse Davis},
  booktitle = {Proceedings of the 25th ACM SIGKDD International Conference
               on Knowledge Discovery \& Data Mining},
  pages     = {1851--1861},
  year      = {2019},
  doi       = {10.1145/3292500.3330758}
}

@inproceedings{Decroos2020AtomicSPADL,
  title     = {Interpretable Prediction of Goals in Soccer},
  author    = {Tom Decroos and Jesse Davis},
  booktitle = {Proceedings of the AAAI-20 Workshop on Artificial Intelligence
               in Team Sports},
  year      = {2020}
}

Contributing

See CONTRIBUTING.md for development setup, coding standards, and PR process. Open items and planned work are tracked in TODO.md.

License

MIT License. See LICENSE for details.

Project details


Release history Release notifications | RSS feed

This version

3.2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

silly_kicks-3.2.0.tar.gz (11.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

silly_kicks-3.2.0-py3-none-any.whl (209.1 kB view details)

Uploaded Python 3

File details

Details for the file silly_kicks-3.2.0.tar.gz.

File metadata

  • Download URL: silly_kicks-3.2.0.tar.gz
  • Upload date:
  • Size: 11.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for silly_kicks-3.2.0.tar.gz
Algorithm Hash digest
SHA256 69b813611e0845a8d5236864b90946edf57aec3864771bb05008b7692d3e3956
MD5 6d53543d5d37e98b798cadfabdcf99cb
BLAKE2b-256 f48a4d3a49e99e312498475ba1101c63e0ddbab9bff1592da9d2312403ab30fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for silly_kicks-3.2.0.tar.gz:

Publisher: publish.yml on karsten-s-nielsen/silly-kicks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file silly_kicks-3.2.0-py3-none-any.whl.

File metadata

  • Download URL: silly_kicks-3.2.0-py3-none-any.whl
  • Upload date:
  • Size: 209.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for silly_kicks-3.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc955f482b3f13095e04508becda5f27b8ba2939385405b0e8ee8f3083e03b55
MD5 f6524740a2a926ebbe9f92cb500aa37c
BLAKE2b-256 be1cd9fd6821c8639ac9af6a2947885f7db12dad68c2e9151ccefbf28036f1be

See more details on using hashes here.

Provenance

The following attestation bundles were made for silly_kicks-3.2.0-py3-none-any.whl:

Publisher: publish.yml on karsten-s-nielsen/silly-kicks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page