{ "cells": [ { "cell_type": "markdown", "id": "45ef0eb0", "metadata": {}, "source": [ "# 📍 Recipe: Shot Accuracy per Team\n", "\n", "This example shows how to calculate shot accuracy - the percentage of shots that were on target - for each team in a match.\n", "\n", "## 🧰 What You'll Learn\n", "\n", "- How to access StatsBomb data using `Flow.statsbomb` methods\n", "- How to filter for shots\n", "- How to define custom group-level aggregations\n", "- How to compute derived metrics like accuracy %\n", "\n", "## Imports" ] }, { "cell_type": "code", "execution_count": 1, "id": "4eccffb9", "metadata": {}, "outputs": [], "source": [ "from penaltyblog.matchflow import Flow, where_equals" ] }, { "cell_type": "markdown", "id": "96f05455", "metadata": {}, "source": [ "## Load the Data" ] }, { "cell_type": "code", "execution_count": 2, "id": "21eb6bbe", "metadata": {}, "outputs": [], "source": [ "# Load events for a StatsBomb match\n", "match_id = 22912 # Champions League Final 2018/2019\n", "\n", "flow = Flow.statsbomb.events(match_id)" ] }, { "cell_type": "markdown", "id": "31af92fc", "metadata": {}, "source": [ "## Define our Custom Aggregation Function" ] }, { "cell_type": "code", "execution_count": 3, "id": "b9f1ff67", "metadata": {}, "outputs": [], "source": [ "def shot_accuracy(records):\n", " total = 0\n", " on_target = 0\n", " for r in records:\n", " total += 1\n", " if r.get(\"outcome\") in (\"Goal\", \"Saved\"):\n", " on_target += 1\n", " return round((on_target / total) * 100, 1) if total else 0.0" ] }, { "cell_type": "markdown", "id": "ab996c14", "metadata": {}, "source": [ "## Calculate Shot Accuracy" ] }, { "cell_type": "code", "execution_count": 4, "id": "a7db20ac", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/martin/repos/penaltyblog/venv/lib/python3.13/site-packages/statsbombpy/api_client.py:21: NoAuthWarning: credentials were not supplied. open data access only\n", " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "| accuracy_pct | team | total_shots |\n", "|----------------|-------------------|---------------|\n", "| 50 | Tottenham Hotspur | 16 |\n", "| 21.4 | Liverpool | 14 |\n" ] } ], "source": [ "(\n", " flow.filter(where_equals(\"type.name\", \"Shot\"))\n", " .select(\"team.name\", \"shot.outcome.name\")\n", " .rename(**{\"team.name\": \"team\", \"shot.outcome.name\": \"outcome\"})\n", " .group_by(\"team\")\n", " .summary(\n", " {\n", " \"total_shots\": \"count\",\n", " \"accuracy_pct\": shot_accuracy,\n", " }\n", " )\n", " .sort_by(\"accuracy_pct\", ascending=False)\n", " .assign(accuracy_pct=lambda r: round(r[\"accuracy_pct\"], 1))\n", " .show()\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.1" } }, "nbformat": 4, "nbformat_minor": 5 }