📍 Recipe: Touch Location Heatmap for a Player#
In this example, we’ll generate a heatmap of where a single player touched the ball during a match using StatsBomb open data.
We’ll use Flow to filter events, extract coordinates, and then visualize the result using mplsoccer.
🧰 What You’ll Learn#
How to access StatsBomb data using
Flow.statsbombmethodsHow to filter events to those involving a given player
How to extract location data using or
.split_array()How to use
.pipe()to apply a custom function to the Flow
Imports#
[1]:
from IPython.display import HTML
from penaltyblog.matchflow import Flow, where_equals
from penaltyblog.viz import Pitch
import plotly.io as pio
Load the Data#
[2]:
# Load events for a StatsBomb match
match_id = 22912 # Champions League Final 2018/2019
flow = Flow.statsbomb.events(match_id)
Filter Events to Just Those by Trent Alexander-Arnold#
[13]:
touches = (
flow.filter(where_equals("player.name", "Trent Alexander-Arnold"))
.split_array("location", into=["x", "y"])
.select("x", "y")
)
for touch in touches.head(3):
print(touch)
{'x': 43.5, 'y': 65.7}
{'x': 21.9, 'y': 59.6}
{'x': 14.7, 'y': 65.9}
/Users/martin/repos/penaltyblog/venv/lib/python3.13/site-packages/statsbombpy/api_client.py:21: NoAuthWarning:
credentials were not supplied. open data access only
Plot Heatmap of Touches#
[14]:
pitch = Pitch(
provider="statsbomb",
orientation="horizontal",
view="full",
theme="night",
show_axis=False,
show_legend=False,
width=400,
height=400,
title="Trent Alexander-Arnold – Touch Map",
)
pitch.plot_kde(
touches,
x="x",
y="y",
colorscale="Viridis",
)
# NOTE: normally we'd just call `pitch.show()` here, but since
# we're exporting to HTML docs, we need to use `HTML` to export
# the plot
# pitch.show()
HTML(pio.to_html(pitch.fig, include_plotlyjs="cdn"))
[14]: