Por qué empezar con StatsBomb open data
StatsBomb publica un conjunto de competiciones gratuitas con datos de eventos completos: cada pase, conducción, presión y disparo, con coordenadas y contexto. Es el mejor arenero de la analítica de fútbol — sin API key, sin negociar términos, sin scraping.
El catálogo completo vive en el repositorio open-data de GitHub.
Paso 1 — Elige una competición y carga los eventos
El paquete statsbombpy envuelve el JSON crudo:
from statsbombpy import sb
competitions = sb.competitions()
matches = sb.matches(competition_id=11, season_id=90) # La Liga 2020/21
events = sb.events(match_id=matches.iloc[0].match_id)Si prefieres los ficheros crudos — recomendable para aprender, porque ves el esquema — descarga events/{match_id}.json del repositorio y parsea con pandas.json_normalize.
Paso 2 — Convierte eventos en disparos
shots = (
events[events.type == "Shot"]
.assign(
x=lambda df: df.location.apply(lambda loc: loc[0]),
y=lambda df: df.location.apply(lambda loc: loc[1]),
goal=lambda df: df.outcome == "Goal",
)
[["x", "y", "goal", "player", "shot_statsbomb_xg"]]
)
print(shots.groupby("player").agg(shots=("goal", "size"), goals=("goal", "sum")))Dos cosas a notar: las coordenadas están en un campo de 120×80, y los eventos ya traen shot_statsbomb_xg. Usa esa columna para validar tu propio modelo después.
Paso 3 — Dibuja el mapa de disparos
import mplsoccer
import matplotlib.pyplot as plt
pitch = mplsoccer.Pitch(pitch_type="statsbomb", pitch_color="#0d1117")
fig, ax = pitch.draw()
sizes = shots["shot_statsbomb_xg"] * 900 + 60
colors = shots["goal"].map({True: "#00e08a", False: "#4b5563"})
pitch.scatter(shots.x, shots.y, s=sizes, c=colors, alpha=0.85, ax=ax)
ax.set_title("Shots — size = xG, colour = goal", color="white")
plt.show()Paso 4 — Hazlo repetible
Un pipeline que descarga, transforma y dibuja en un solo script se vuelve inmanejable al tercer partido. Sepáralo pronto:
ingest/— descarga el JSON crudo y guárdalo sin tocar (cachea todo; la API es lenta y tiene límites).transform/— parsea eventos a dataframes tidy, una función por entidad (shots,passes,pressures).analysis/— funciones puras sobre los frames: agregaciones, ventanas móviles, comparaciones.notebooks/— solo exploración; en cuanto una transformación se reutiliza, pasa atransform/.
Es el mismo patrón que usa cualquier proyecto serio de datos de fútbol, y el que sobrevive al contacto con un segundo dataset.
Dónde seguir
- Variables para xG — añade presión, parte del cuerpo, disparos a la primera; compara tu AUC con
shot_statsbomb_xg. - Redes de pases — agrega pases por pareja de jugadores y posición.
- Métricas de presión — cuenta presiones por zona y observa qué equipos rompen antes la estructura.
Elige una pregunta, construye el pipeline más pequeño que la responda y publica lo que aprendas. Ese bucle — pregunta, datos, respuesta — es el trabajo real.

