Análisis de Datos de Fútbol con Python
— Al estilo Mister Chip —
Aprende a extraer datos curiosos de 1,900+ partidos de La Liga, Premier League y Serie A. Desde el setup básico hasta visualizaciones profesionales.
Mister Chip es famoso por encontrar esos datos absurdos que nadie espera: "Primera vez que el Atlético pierde 3 partidos seguidos en casa contra equipos catalanes un martes de febrero desde 1987". Parece magia, pero es puro análisis de datos con criterio. Aunque el usa Excel nosotros lo haremos con Python.
En esta guía te enseño a montar tu propio sistema de análisis de fútbol desde cero. Usaremos un dataset real de 1,943 partidos de la temporada 2024/2025 y Python para extraer insights que podrías vender a cualquier periódico deportivo.
🛠️ Paso 1: Setup Inicial con Python
Antes de tocar un solo dato, necesitas preparar tu entorno. Esto es lo que instalaremos:
- pandas — Manipulación de datos (el corazón del análisis)
- matplotlib — Gráficos básicos
- seaborn — Gráficos estadísticos bonitos
- numpy — Operaciones matemáticas
Para seguir este tutorial, primero descarga el dataset de partidos de fútbol 2024/2025:
⬇️ Descargar Dataset en Kaggle
Contiene 1,943 partidos de Premier League, La Liga y Serie A.
Abre tu terminal y ejecuta:
pip install pandas matplotlib seaborn numpy
Ahora creamos nuestro archivo de análisis. Yo lo llamaré analisis_futbol.py:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
# Configuración visual (tema oscuro profesional)
plt.style.use('dark_background')
sns.set_palette('husl')
# Cargar el dataset
df = pd.read_csv('football_matches_2024_2025.csv')
# Ver las primeras filas
print(df.head())
Siempre usa plt.style.use('dark_background') si vas a publicar gráficos en redes sociales o
blogs con tema oscuro. Quedan mucho más profesionales que los gráficos blancos por defecto.
🔍 Paso 2: Explorar el Dataset
Antes de buscar datos curiosos, necesitas entender qué tienes entre manos. Ejecuta estos comandos:
print(df.columns.tolist())
# Dimensiones del dataset
print(f"Filas: {df.shape[0]}, Columnas: {df.shape[1]}")
# Resumen estadístico
print(df.describe())
'matchday', 'stage', 'status', 'date_utc', 'referee', 'home_team_id',
'home_team', 'away_team_id', 'away_team', 'fulltime_home', 'fulltime_away',
'halftime_home', 'halftime_away', 'goal_difference', 'total_goals',
'match_outcome', 'home_points', 'away_points', 'referee_id']
Filas: 1943, Columnas: 23
Tenemos 23 variables para jugar. Las más interesantes son:
| Columna | Descripción | Uso Principal |
|---|---|---|
competition_name |
Nombre de la liga | Filtrar por liga |
home_team / away_team |
Nombres de equipos | Análisis por equipo |
fulltime_home / fulltime_away |
Goles al final | Resultados |
halftime_home / halftime_away |
Goles al descanso | Remontadas |
match_outcome |
Home Win / Away Win / Draw | Clasificar resultados |
referee |
Nombre del árbitro | Análisis de árbitros |
📊 Infografía: Estructura del dataset y columnas clave para análisis
🎯 Paso 3: 5 Datos tipo "Mister Chip"
Ahora viene lo divertido. Vamos a extraer datos curiosos que podrías tuitear y conseguir miles de RT. El secreto está en hacer preguntas muy específicas.
📊 Dato #1: El Equipo "Remontador" de la Temporada
¿Qué equipo ha remontado más veces perdiendo al descanso?
# Remontadas LOCALES (perdían y ganaron)
remontadas_local = df[
(df['halftime_home'] < df[ 'halftime_away']) &
(df['match_outcome'] == 'Home Win')
]
# Contar por equipo
top_remontadores = remontadas_local.groupby('home_team').size().sort_values(ascending=False)
print(top_remontadores.head(5))
🔥 El FC Barcelona y el Liverpool FC son los reyes de las remontadas en casa esta temporada, con 3 partidos cada uno ganados tras ir perdiendo al descanso.
Esto indica fortaleza mental y ajustes tácticos efectivos en el vestuario.
📊 Dato #2: El Partido con Más Goles
mas_goles = df.loc[df['total_goals'].idxmax()]
print(f"Partido: {mas_goles['home_team']} vs {mas_goles['away_team']}")
print(f"Resultado: {mas_goles['fulltime_home']}-{mas_goles['fulltime_away']}")
print(f"Total goles: {mas_goles['total_goals']}")
print(f"Liga: {mas_goles['competition_name']}")
⚽ El partido con más goles de la temporada fue Tottenham 3-6 Liverpool (9 goles) en la Premier League.
El siguiente fue el Brentford 4-3 Ipswich (7 goles). La Premier es claramente la liga más espectacular.
📊 Dato #3: La Liga con Más Goles por Partido
goles_por_liga = df.groupby('competition_name')['total_goals'].mean().sort_values(ascending=False)
print(goles_por_liga.round(2))
Premier League 2.87
Serie A 2.58
La Liga 2.53
🏴 La Premier League es la liga más espectacular de Europa con 2.87 goles por partido, un 13% más que La Liga.
📊 Dato #4: El Árbitro "Goleador"
¿Qué árbitro dirige los partidos con más goles? Esto podría indicar un estilo más permisivo.
arbitros = df.groupby('referee').agg({
'total_goals': 'mean',
'match_id': 'count'
}).rename(columns={'match_id': 'partidos'})
# Filtrar árbitros con más de 10 partidos
arbitros_top = arbitros[arbitros['partidos'] >= 10].sort_values('total_goals', ascending=False)
print(arbitros_top.head(5).round(2))
🎯 Andy Madley (Premier League) dirige los partidos con más goles: 3.4 goles de media. En contraste, César Soto Grado (La Liga) promedia solo 2.1 goles.
¿Coincidencia o estilo de arbitraje más permisivo?
📊 Dato #5: El Equipo "0-0 King"
¿Qué equipo ha participado en más empates a cero?
empates_cero = df[(df['fulltime_home'] == 0) & (df['fulltime_away'] == 0)]
# Contar participaciones (como local o visitante)
ceros_local = empates_cero['home_team'].value_counts()
ceros_visit = empates_cero['away_team'].value_counts()
# Sumar ambos
total_ceros = ceros_local.add(ceros_visit, fill_value=0).sort_values(ascending=False)
print(total_ceros.head(5).astype(int))
😴 El Getafe CF es el "Rey del 0-0" esta temporada con 5 empates sin goles. Le sigue el Everton con 4.
El fútbol defensivo sigue vivo en ciertos equipos.
🎯 Infografía: Los 5 datos curiosos que encontramos en el dataset
📈 Paso 4: Visualizaciones Profesionales
Los datos en bruto están bien, pero una visualización vale más que mil números. Vamos a crear gráficos que puedas publicar directamente.
Gráfico 1: Distribución de Resultados por Liga
fig, ax = plt.subplots(figsize=(12, 6))
# Calcular porcentajes por liga
resultados = df.groupby(['competition_name', 'match_outcome']).size().unstack(fill_value=0)
resultados_pct = resultados.div(resultados.sum(axis=1), axis=0) * 100
# Crear el gráfico
resultados_pct.plot(kind='bar', ax=ax, color=['#4ade80', '#ef4444', '#fbbf24'])
ax.set_title('Distribución de Resultados por Liga (2024/25)', fontsize=16, fontweight='bold')
ax.set_ylabel('Porcentaje (%)')
ax.set_xlabel('')
ax.legend(['Empate', 'Victoria Local', 'Victoria Visitante'])
plt.xticks(rotation=0)
plt.tight_layout()
plt.savefig('resultados_por_liga.png', dpi=150)
plt.show()
📊 Gráfico 1: Distribución de resultados (victorias locales, visitantes y empates) por liga
Gráfico 2: Top 10 Equipos Goleadores
goles_local = df.groupby('home_team')['fulltime_home'].sum()
goles_visit = df.groupby('away_team')['fulltime_away'].sum()
# Sumar totales
goles_totales = goles_local.add(goles_visit, fill_value=0).sort_values(ascending=False)
# Top 10
top10 = goles_totales.head(10)
# Gráfico horizontal
fig, ax = plt.subplots(figsize=(10, 8))
colors = ['#4ade80' if 'Barcelona' in x or 'Madrid' in x else '#3b82f6' for x in top10.index]
ax.barh(top10.index, top10.values, color=colors)
ax.invert_yaxis() # Mayor arriba
ax.set_xlabel('Goles Totales (2024/25)')
ax.set_title('Top 10 Equipos Más Goleadores de Europa', fontweight='bold')
# Añadir valores en las barras
for i, v in enumerate(top10.values):
ax.text(v + 1, i, str(int(v)), va='center', fontweight='bold')
plt.tight_layout()
plt.savefig('top10_goleadores.png', dpi=150)
plt.show()
groupby + sum: Agrupa partidos por equipo y suma sus goles.
.add(fill_value=0): Combina goles locales y visitantes en un solo total.
ax.barh: Gráfico de barras horizontal (más legible para rankings).
ax.text: Añade el valor numérico al final de cada barra.
📊 Gráfico 2: Top 10 equipos más goleadores de Europa (temporada 2024/25)
🐍 Infografía: El workflow completo de análisis de datos deportivos con Python
🚀 Paso 5: Análisis Avanzado (Heatmaps y Correlaciones)
Para impresionar de verdad, necesitas ir más allá. Vamos a crear un heatmap que muestre qué equipos se "hacen daño" entre ellos.
# Filtrar solo La Liga para este ejemplo
liga = df[df['competition_name'] == 'La Liga']
# Crear tabla pivote
matriz = liga.pivot_table(
index='home_team',
columns='away_team',
values='fulltime_home',
aggfunc='sum',
fill_value=0
)
# Crear heatmap
fig, ax = plt.subplots(figsize=(14, 12))
sns.heatmap(matriz, cmap='Greens', annot=False, linewidths=0.5, ax=ax)
ax.set_title('Goles marcados por Local vs Visitante (La Liga 24/25)', fontweight='bold')
plt.tight_layout()
plt.savefig('heatmap_laliga.png', dpi=150)
📊 Gráfico 3: Heatmap de enfrentamientos — Goles marcados por cada equipo local contra cada visitante
Las celdas más oscuras indican enfrentamientos donde el equipo local metió muchos goles al visitante. Puedes identificar rápidamente:
- "Víctimas favoritas" — Equipos que siempre sufren contra ciertos rivales
- "Fortalezas en casa" — Equipos que golea a todos en su estadio
- "Partidos aburridos" — Combinaciones que siempre acaban 0-0 o 1-0
❓ Preguntas Frecuentes
Descarga el CSV con 1,943 partidos y el Jupyter Notebook con todo el código listo para ejecutar. Solo tienes que suscribirte a mi newsletter de Data Analytics.
Descargar Dataset Gratis