Módulo 3: Creando nuevas métricas - La pizarra del entrenador
La pizarra del entrenador: más allá de los datos crudos
Hasta ahora, hemos trabajado como detectives: hemos cargado datos y hemos aprendido a filtrar para encontrar la evidencia que buscábamos. Pero un analista de élite no solo encuentra la información, sino que también la crea.
Los sets de datos que recibimos (los datos crudos) son solo el punto de partida. A menudo contienen las estadísticas básicas: la posición (x, y) de un pase, el tipo de evento, el jugador implicado. Sin embargo, las preguntas tácticas más interesantes requieren métricas que no vienen precalculadas. Por ejemplo, ¿a qué distancia de la portería se realizó un tiro? ¿Fue un pase “progresivo” que rompió líneas defensivas?
Aquí es donde entra en juego una de las habilidades más importantes en la ciencia de datos: la ingeniería de características (feature engineering). Suena complejo, pero la idea es simple: usar los datos existentes para crear nuevas columnas (nuevas “características”) que hagan nuestro análisis más potente.
Imagínalo como el trabajo de un entrenador en la pizarra táctica. El entrenador no solo ve a los jugadores (los datos crudos), sino que dibuja flechas y conexiones para crear jugadas y estrategias (las nuevas métricas). En este módulo, aprenderemos a ser ese entrenador: tomaremos nuestros datos base y los enriqueceremos para descubrir los patrones tácticos que se esconden en ellos.
Operaciones básicas con columnas
La forma más directa de crear una nueva métrica es realizando operaciones aritméticas (+
, -
, *
, /
) entre las columnas que ya existen en nuestro DataFrame. Pandas está diseñado para que esto sea increíblemente intuitivo. Si le pides que reste dos columnas, él entenderá que debe realizar la operación fila por fila.
Vamos a verlo con un caso práctico muy relevante en el análisis de fútbol: medir la calidad de la finalización de un tiro.
Para esto, usaremos dos métricas avanzadas que a menudo vienen en los sets de datos de eventos:
- xG (Goles Esperados): La probabilidad de que un tiro termine en gol, basada en factores como la distancia, el ángulo, etc. Un
xG
de0.3
significa que un tiro desde esa posición suele ser gol el 30% de las veces. - xGOT (Goles Esperados a Portería): Mide la calidad del tiro una vez que ha salido del pie del jugador. Considera a dónde fue dirigido el balón dentro de la portería. Un
xGOT
alto en un tiro conxG
bajo significa una finalización excepcional.
Caso práctico: calculando la calidad de la finalización
Podemos crear una nueva métrica, que llamaremos diferencia_finalizacion
, simplemente restando el xG
del xGOT
. Un valor positivo alto en esta nueva columna nos indicará que el jugador mejoró significativamente una oportunidad de gol gracias a la calidad de su disparo.
En tu Jupyter Notebook, primero asegúrate de tener un DataFrame con los tiros de un partido.
# Asumimos que ya tienes el DataFrame 'tiros' del módulo anterior
# Si no, puedes volver a crearlo:
# mascara_tiros = match_data['result'] == 'Shot'
# tiros = match_data[mascara_tiros]
# Creamos la nueva columna 'diferencia_finalizacion'
# Pandas realiza la resta fila por fila automáticamente
tiros['diferencia_finalizacion'] = tiros['xGOT'] - tiros['xG']
# Exploremos el resultado
# Mostramos las columnas relevantes para ver nuestra nueva métrica en acción
print("Análisis de finalización de los primeros 5 tiros:")
print(tiros[['player', 'xG', 'xGOT', 'diferencia_finalizacion']].head())
Con una sola línea de código, hemos añadido una nueva capa de información a nuestro análisis. Ya no solo sabemos la calidad de la oportunidad (xG
), sino también la calidad de la ejecución del tiro (diferencia_finalizacion
).
Esta técnica de operar directamente con columnas es la base de la ingeniería de características. En la siguiente sección, aprenderemos a realizar transformaciones más complejas que no se pueden resolver con una simple operación matemática, utilizando el poderoso método .apply()
.
Aplicando funciones a las columnas
Las operaciones matemáticas directas son útiles, pero a menudo necesitamos realizar transformaciones más complejas. ¿Qué pasa si queremos convertir las coordenadas de un evento, que suelen venir en un sistema de 100x100, a metros para que nuestros cálculos de distancia sean más realistas? Esto requiere una lógica más elaborada que una simple suma o resta.
Para estos casos, Pandas nos ofrece un método muy potente: .apply()
. Este método nos permite tomar una función de Python que hayamos definido y “aplicarla” a cada uno de los valores de una columna, generando una nueva columna con los resultados.
Caso práctico: convirtiendo coordenadas a metros
En muchos sets de datos de eventos, las coordenadas x
e y
del campo se representan en una escala de 0 a 100. Para un análisis más preciso, nos conviene convertirlas a las dimensiones de un campo de fútbol real (aproximadamente 105 metros de largo por 68 de ancho).
Primero, definiremos una función simple en Python que tome una coordenada y la convierta a su equivalente en metros.
# Asumimos que 'match_data' ya está cargado
# 1. Definimos nuestras funciones de conversión
# Una para el eje X (largo del campo) y otra para el eje Y (ancho)
def convertir_x_a_metros(coordenada_x):
return coordenada_x * 1.05
def convertir_y_a_metros(coordenada_y):
return coordenada_y * 0.68
# 2. Aplicamos estas funciones a las columnas 'x' e 'y' para crear las nuevas
match_data['x_metros'] = match_data['x'].apply(convertir_x_a_metros)
match_data['y_metros'] = match_data['y'].apply(convertir_y_a_metros)
# 3. Verificamos el resultado
print("Coordenadas originales vs. convertidas a metros:")
print(match_data[['x', 'x_metros', 'y', 'y_metros']].head())
Salida:
x x_metros y y_metros
0 50.0 52.50 50.0 34.00
1 58.9 61.84 43.4 29.51
2 74.8 78.54 29.9 20.33
3 25.4 26.67 39.6 26.93
4 32.0 33.60 28.0 19.04
Con el método .apply()
, hemos ejecutado nuestra lógica personalizada sobre miles de filas de forma eficiente y hemos añadido dos nuevas columnas a nuestro DataFrame que lo hacen mucho más útil para análisis espaciales.
Esta técnica de definir una función y aplicarla a una columna es una de las más versátiles en Pandas. Te permite implementar casi cualquier tipo de transformación de datos que puedas imaginar. En la siguiente sección, usaremos estas nuevas columnas para calcular una de las métricas más importantes en el análisis de tiros.
Creando métricas espaciales: la distancia al gol
Hemos transformado nuestras coordenadas a una escala real en metros. Ahora podemos empezar a hacer preguntas espaciales, y una de las más importantes es: ¿a qué distancia de la portería se realizó un tiro? Esta métrica es fundamental para evaluar la calidad de las oportunidades de gol y el estilo de juego de un equipo o jugador.
Para calcular la distancia, usaremos un concepto matemático que probablemente recuerdes de la escuela: el Teorema de Pitágoras. La distancia entre dos puntos (en nuestro caso, la ubicación del tiro y el centro de la portería) es la hipotenusa de un triángulo rectángulo.
La fórmula es: distancia = √((x2 - x1)² + (y2 - y1)²)
.
Caso práctico: calculando la distancia de cada tiro
Asumiremos que la portería rival se encuentra en las coordenadas (105, 34)
en nuestro sistema de metros (105m de largo, y el centro de la portería está a 34m del borde).
Primero, filtraremos nuestro DataFrame para quedarnos solo con los tiros, ya que no tiene sentido calcular la distancia a portería para un pase en nuestro propio campo. Luego, aplicaremos la fórmula.
import numpy as np # Necesitaremos numpy para la raíz cuadrada (sqrt)
# Asumimos que 'match_data' ya tiene las columnas 'x_metros' e 'y_metros'
# 1. Filtramos para quedarnos solo con los tiros
tiros = match_data[match_data['result'] == 'Shot'].copy()
# 2. Definimos las coordenadas de la portería rival
porteria_x = 105
porteria_y = 34
# 3. Aplicamos la fórmula de la distancia euclidiana para crear la nueva columna
tiros['distancia_a_porteria'] = np.sqrt(
(porteria_x - tiros['x_metros'])**2 +
(porteria_y - tiros['y_metros'])**2
)
# 4. Verificamos el resultado
print("Distancia a portería de los primeros 5 tiros:")
# Usamos .round(2) para redondear el resultado a dos decimales y hacerlo más legible
print(tiros[['player', 'distancia_a_porteria']].head().round(2))
Nota: Usamos .copy()
al filtrar los tiros para evitar una advertencia común de Pandas (SettingWithCopyWarning
) al crear nuevas columnas en una porción de un DataFrame.
Salida:
Distancia a portería de los primeros 5 tiros:
player distancia_a_porteria
21 Mohamed Salah 14.59
35 Mohamed Salah 26.68
115 Alexis Mac Allister 28.05
131 Cody Gakpo 11.87
189 Darwin Núñez 19.54
Has creado tu primera métrica espacial compleja. Esta nueva columna, distancia_a_porteria
, es increíblemente valiosa. Nos permite analizar si un jugador tiende a tirar desde lejos, si un equipo genera oportunidades cercanas a la portería, y es uno de los componentes clave para modelos más avanzados como los Goles Esperados (xG).
En la sección final de este módulo, haremos un resumen de lo aprendido y te daremos un avance de lo que nos espera.
El siguiente nivel: de eventos a patrones
¡Misión cumplida! En este módulo, has dado uno de los saltos más importantes en tu carrera como analista: has pasado de ser un consumidor de datos a ser un creador de métricas.
Hemos transformado nuestro set de datos crudos en una fuente de información mucho más rica y con un contexto táctico real. Aprendimos a:
- Realizar operaciones directas entre columnas para crear métricas de comparación, como la calidad de la finalización de un tiro.
- Aplicar funciones personalizadas con
.apply()
para realizar transformaciones complejas, como convertir las coordenadas del campo a metros. - Utilizar esos nuevos datos para calcular métricas espaciales, como la distancia de un tiro a la portería.
Ya no solo ves los datos; ahora puedes enriquecerlos para que cuenten una historia más profunda. Has añadido tu propia inteligencia a la información.
Sin embargo, hasta ahora, nuestro análisis se ha centrado en eventos individuales. En el próximo módulo, cambiaremos nuestra perspectiva. Dejaremos de mirar jugada por jugada y empezaremos a ver el panorama completo. Aprenderemos a agrupar nuestros datos para responder preguntas a nivel de equipo y de jugador, como: ¿qué jugador realizó más pases progresivos en todo el partido? o ¿qué equipo tuvo el promedio de xG
más alto? Es el siguiente paso para empezar a identificar patrones tácticos a gran escala.