📍 Recipe: Shot Accuracy per Team#

This example shows how to calculate shot accuracy - the percentage of shots that were on target - for each team in a match.

🧰 What You’ll Learn#

  • How to access StatsBomb data using Flow.statsbomb methods

  • How to filter for shots

  • How to define custom group-level aggregations

  • How to compute derived metrics like accuracy %

Imports#

[1]:
from penaltyblog.matchflow import Flow, where_equals

Load the Data#

[2]:
# Load events for a StatsBomb match
match_id = 22912  # Champions League Final 2018/2019

flow = Flow.statsbomb.events(match_id)

Define our Custom Aggregation Function#

[3]:
def shot_accuracy(records):
    total = 0
    on_target = 0
    for r in records:
        total += 1
        if r.get("outcome") in ("Goal", "Saved"):
            on_target += 1
    return round((on_target / total) * 100, 1) if total else 0.0

Calculate Shot Accuracy#

[4]:
(
    flow.filter(where_equals("type.name", "Shot"))
    .select("team.name", "shot.outcome.name")
    .rename(**{"team.name": "team", "shot.outcome.name": "outcome"})
    .group_by("team")
    .summary(
        {
            "total_shots": "count",
            "accuracy_pct": shot_accuracy,
        }
    )
    .sort_by("accuracy_pct", ascending=False)
    .assign(accuracy_pct=lambda r: round(r["accuracy_pct"], 1))
    .show()
)
/Users/martin/repos/penaltyblog/venv/lib/python3.13/site-packages/statsbombpy/api_client.py:21: NoAuthWarning: credentials were not supplied. open data access only
  warnings.warn(
|   accuracy_pct | team              |   total_shots |
|----------------|-------------------|---------------|
|           50   | Tottenham Hotspur |            16 |
|           21.4 | Liverpool         |            14 |