Qué mide realmente el xG

Cada disparo ocurre en un contexto: distancia a portería, ángulo, parte del cuerpo, presión, si vino de balón parado, si el portero estaba colocado. Un modelo de goles esperados convierte esas variables en una probabilidad — la probabilidad de que un jugador medio marque desde esa situación exacta.

No es una predicción del partido. Es una medida de la calidad de las ocasiones: si un equipo acumula 2,3 xG con veinte disparos, el modelo dice que "ese montón de ocasiones, repetido infinitas veces, vale unos 2,3 goles".

Para qué sirve

  • Separar proceso de resultados. En cinco partidos, los goles son ruido; el xG se estabiliza mucho antes. Un equipo que genera 1,8 xG y marca 0,6 o tiene mala suerte o tiene un problema de definición — ambas cosas merecen mirarse.
  • Comparar perfiles de disparo. Dos equipos pueden tirar 14 veces: uno desde dentro del área con ángulo central, otro desde 25 metros. El xG hace visible esa diferencia.
  • Hablar de defensa sin balón. Un xG concedido bajo suele ser mejor señal de estructura sólida que "concedemos pocos tiros".

Dónde falla

  • Cada proveedor da números distintos. StatsBomb, Opta y Understat publican xG y no coinciden — a veces con diferencias del 15–20% en el mismo disparo. Distinta recogida de datos, distintas variables, distinto entrenamiento.
  • Ignora al jugador. El modelo da el mismo valor al mismo disparo sin importar quién lo tira. Los modelos post-shot (que añaden dónde acabó el balón dentro de la portería) corrigen parte de esto, pero el xG pre-shot no puede.
  • Un partido no prueba nada. Una diferencia de 0,4 xG en un solo partido está dentro del ruido. El xG es una herramienta para muestras, no para titulares.

Cómo usarlo con criterio

  1. Trátalo como base, no como veredicto. La pregunta interesante no es "quién mereció ganar" sino "qué nos dice la diferencia".
  2. Acompáñalo siempre de volumen. 0,9 xG con 5 disparos y 0,9 xG con 20 disparos son historias distintas.
  3. Mira la tendencia, no el valor. Las medias móviles de cinco partidos ganan a los números de un partido, siempre.

Constrúyelo tú en 20 líneas

El núcleo de un modelo xG simple es una regresión logística sobre unas pocas variables: distancia, ángulo y si el disparo fue de cabeza o penalti.

import pandas as pd
from sklearn.linear_model import LogisticRegression

def distance(x, y):
    return ((120 - x) ** 2 + (40 - y) ** 2) ** 0.5

def angle(x, y):
    left = abs(y - 36)
    right = abs(y - 44)
    import math
    return math.atan2(7.32 * (120 - x), (120 - x) ** 2 + (36 - y) * (44 - y))

shots["distance"] = [distance(x, y) for x, y in zip(shots.x, shots.y)]
shots["angle"] = [angle(x, y) for x, y in zip(shots.x, shots.y)]

model = LogisticRegression()
model.fit(shots[["distance", "angle", "is_header"]], shots["goal"])
shots["xG"] = model.predict_proba(shots[["distance", "angle", "is_header"]])[:, 1]

Ese modelo no ganará al de un proveedor, pero te enseñará más sobre el xG que cualquier dashboard: cada variable que añadas, cada sesgo que introduzcas, se vuelve visible.

TL;DR

El xG es una métrica de calidad de ocasión que se estabiliza rápido, compara cosas comparables y miente con seguridad en muestras pequeñas. Úsalo como lente, no como juez.