Saltar al contenido

Blog Datos · Tutorial Python

Análisis de datos de fútbol con Python al estilo Mister Chip

Un CSV gratuito por liga, pandas y los 1.752 partidos de la temporada 2025/26: goles, ventaja de local, remontadas y árbitros. Y la prueba del sorteo, para saber cuándo un dato curioso es pura casualidad.

Ariel Castillo Actualizado 10 min de lectura
Portada: barras con los goles por partido de las cinco grandes ligas en 2025/26, LaLiga destacada, y el titular «El dato curioso y la historia falsa»

¿Cuántas veces gana el equipo que se va al descanso perdiendo? En las cinco grandes ligas europeas, en 2025/26, 87 veces de 1.049: el 8,3 %. O sea, tu cuñado, el que jura en el descanso que «este equipo remonta seguro», acierta menos de una vez de cada diez. Esa clase de frase, exacta y con denominador, es la especialidad de Mister Chip. En esta guía de análisis de datos de fútbol con Python la sacás vos de un CSV gratuito con pandas y, antes de publicarla, comprobás que no sea una casualidad disfrazada de historia.1

1.752Partidos de las cinco grandes ligas en 2025/26football-data.co.uk · cálculo propio
2,76Goles por partido (4.844 en total)Cinco ligas · 2025/26
44,0 %Partidos que ganó el localEmpate 25,5 % · visitante 30,5 %
8,3 %Gana el que pierde al descanso87 de 1.049 · 2025/26

Qué tiene un dato al estilo Mister Chip

Alexis Martín-Tamayo, Mister Chip, es un comentarista deportivo nacido en Badajoz e ingeniero de telecomunicación por la Universidad de Sevilla. Su biografía en ESPN destaca lo rápido que reúne datos de casi cualquier deporte.3 Su base de datos juega en otra liga, pero la forma se puede copiar. Un dato así tiene cinco piezas, y si falta una, se cae:

  1. Pregunta¿Gana el que pierde al descanso?
  2. DefiniciónPerdía al descanso y ganó al final
  3. DenominadorLos 1.049 equipos que perdían al descanso
  4. Cálculopandas cuenta 87 casos: 8,3 %
  5. MatizUna temporada y cinco ligas: nada de «récord histórico»

La definición manda: este dataset solo trae el marcador del descanso y el final, así que acá «remontar» es perder al descanso y ganar al final. Si cambiás la definición, cambia el número.

Los datos de fútbol: un CSV gratis por liga y temporada

La fuente es football-data.co.uk, que publica gratis en CSV los resultados de las grandes ligas europeas desde 1993/94, un archivo por liga y temporada.1 Ojo con la letra chica: el uso gratuito es para particulares. Para aprender, perfecto; para un producto comercial, preguntá antes.

ColumnaQué guardaEjemplo (Liverpool-Bournemouth, 15/08/2025)
HomeTeam, AwayTeamEquipo local y visitanteLiverpool, Bournemouth
FTHG, FTAGGoles del local y del visitante al final4, 2
FTRResultado: H gana el local, D empate, A gana el visitanteH
HTHG, HTAGGoles al descanso1, 0
RefereeÁrbitro (solo en la Premier League)A Taylor

La clave completa de columnas está en sus notas.2 Si nunca usaste pandas, empezá por el tutorial de salarios con datos del INE.

Python · cargar las cinco ligas
import pandas as pd

URL = "https://football-data.co.uk/mmz4281/{temp}/{liga}.csv"
LIGAS = {"E0": "Premier League", "SP1": "LaLiga", "I1": "Serie A",
         "D1": "Bundesliga", "F1": "Ligue 1"}
COLUMNAS = ["Date", "HomeTeam", "AwayTeam", "FTHG", "FTAG", "FTR",
            "HTHG", "HTAG", "Referee"]   # Referee solo existe en la Premier

def cargar(temp="2526"):
    partes = []
    for codigo, nombre in LIGAS.items():
        df = pd.read_csv(URL.format(temp=temp, liga=codigo),
                         usecols=lambda c: c in COLUMNAS)
        df = df.dropna(subset=["FTHG", "FTAG"])   # algunas temporadas traen filas vacías
        partes.append(df.assign(liga=nombre))
    df = pd.concat(partes, ignore_index=True)
    return df.assign(goles=df["FTHG"] + df["FTAG"])

df = cargar()
print(df.groupby("liga").size())
Bundesliga 306 · LaLiga 380 · Ligue 1 306 · Premier League 380 · Serie A 380

Validá antes de buscar titulares

Antes de buscar el dato curioso, comprobá que el archivo no tenga partidos repetidos ni celdas vacías, y que sus goles coincidan con otra fuente.

Python · validar antes de analizar
clave = ["liga", "Date", "HomeTeam", "AwayTeam"]
assert not df.duplicated(clave).any()            # ningún partido repetido
assert (df["HomeTeam"] != df["AwayTeam"]).all()   # nadie juega contra sí mismo
print(df[["FTHG", "FTAG", "HTHG", "HTAG"]].isna().sum().sum())   # celdas vacías

print(df.groupby("liga")["goles"].sum())         # para cruzar con otra fuente
0
Bundesliga 990 · LaLiga 1024 · Ligue 1 863 · Premier League 1045 · Serie A 922

Los cinco totales coinciden con los de Wikipedia.6 Si no coincidieran, el problema sería tuyo hasta demostrar lo contrario.

Una celda vacía también cuenta algo

Si cargás 2024/25, aparece un partido sin marcador al descanso: Union Berlin 0-2 Bochum. En el campo fue 1-1, pero un mechero lanzado desde la grada golpeó al portero visitante y la federación alemana le dio el partido al Bochum por 2-0.4 El CSV guarda el resultado oficial. Antes de borrar una fila rara, averiguá por qué es rara.

Validar también sirve para revisar tu propio trabajo.

Me pasó

La versión anterior de este artículo usaba un dataset de Kaggle con «1.943 partidos de tres ligas» de 2024/25. El enlace ya no existe y las cuentas no cerraban: tres ligas de 20 equipos juegan 1.140 partidos, y la Premier 2024/25 tuvo 2,93 goles por partido, no los 2,87 que publiqué.

Goles por liga: la Bundesliga, lejos del resto

Un groupby por liga responde dónde hay más goles y quién gana más en casa.

Python · goles y resultados por liga
resumen = df.groupby("liga").agg(
    goles_por_partido=("goles", "mean"),
    gana_local=("FTR", lambda r: (r == "H").mean() * 100),
    gana_visitante=("FTR", lambda r: (r == "A").mean() * 100),
)
print(resumen.round(2).sort_values("goles_por_partido", ascending=False))
Bundesliga 3.24 · 43.79 · 31.70
Ligue 1 2.82 · 46.08 · 29.41
Premier League 2.75 · 42.63 · 30.00
LaLiga 2.69 · 48.95 · 26.58
Serie A 2.43 · 38.95 · 35.00
La Bundesliga fue la liga con más goles por partido Goles por partido en 2025/26. Línea discontinua: media de las cinco ligas.
LigaGoles por partido
Bundesliga3,24
Ligue 12,82
Premier League2,75
LaLiga2,69
Serie A2,43

Fuente: football-data.co.uk, 2025/26. Cálculo propio, 4 de octubre de 2026.

Entre la Bundesliga y la Serie A hay 0,81 goles por partido: en una temporada de 306 partidos, unos 250 goles. O sea, siete goles más por jornada. ¿Y si es solo el Bayern, que hizo 122 en 34 partidos? Sacá sus partidos: el resto de la Bundesliga promedia 3,06, todavía lo más alto de las cinco. El Bayern infla la media, pero no la explica solo.

Cuántos goles tiene un partido y qué marcador se repite más

Una media de 2,76 goles no te dice cómo es un partido típico. Para eso está la distribución.

Python · distribución de goles y marcadores
goles = df["goles"].clip(upper=7)        # 7 significa «7 o más»
print(goles.value_counts(normalize=True).sort_index().mul(100).round(1))

marcador = df["FTHG"].astype(int).astype(str) + "-" + df["FTAG"].astype(int).astype(str)
print(marcador.value_counts().head(3))
0: 6.5 · 1: 17.0 · 2: 23.5 · 3: 23.3 · 4: 15.4 · 5: 8.3 · 6: 3.7 · 7: 2.3
1-1: 205 · 1-0: 166 · 2-1: 158
Casi la mitad de los partidos terminó con 2 o 3 goles % de partidos según el total de goles. Cinco grandes ligas, 2025/26.
Goles en el partido% de partidos
06,5
117,0
223,5
323,3
415,4
58,3
63,7
7 o más2,3

Fuente: football-data.co.uk, 2025/26. Cálculo propio.

El 46,9 % terminó con 2 o 3 goles, y el 0-0, ese que te arruina el domingo, salió 114 veces (6,5 %). Ahora, los marcadores:

El 1-1 fue el marcador más repetido % de partidos con cada resultado (local-visitante), los diez más frecuentes de 2025/26.
Marcador% de partidos
1-111,7
1-09,5
2-19,0
0-17,5
1-27,2
2-06,8
0-06,5
2-25,4
3-15,0
0-25,0

Fuente: football-data.co.uk, 2025/26. Cálculo propio.

El 1-1 ganó con 205 partidos (11,7 %). Pero si no te importa quién jugaba en casa, 1-0 y 0-1 son el mismo resultado y juntos suman el 17,0 %. Con la misma tabla, «el resultado más común es el 1-1» y «es el 1-0» son verdad a la vez. Por eso la definición viaja pegada al número.

Remontadas: el cuñado acierta menos de una vez de cada diez

Para medir remontadas pasá la tabla a formato largo: una fila por equipo y partido. Así preguntás por «el equipo» sin escribir todo dos veces.

Python · formato largo y remontadas
local = pd.DataFrame({"equipo": df["HomeTeam"],
                      "descanso": df["HTHG"] - df["HTAG"],
                      "final": df["FTHG"] - df["FTAG"]})
visita = pd.DataFrame({"equipo": df["AwayTeam"],
                       "descanso": df["HTAG"] - df["HTHG"],
                       "final": df["FTAG"] - df["FTHG"]})
largo = pd.concat([local, visita], ignore_index=True)   # una fila por equipo y partido

perdian = largo[largo["descanso"] < 0]
print(len(perdian), round((perdian["final"] > 0).mean() * 100, 1))
print(perdian[perdian["final"] > 0]["equipo"].value_counts().head(1))
1049 8.3
Aston Villa 4
De cada 100 equipos que se van perdiendo al descanso, 8 ganan Resultado final de los 1.049 que perdían al descanso en 2025/26. El resto perdió.
Resultado final%
Ganan8,3
Empatan17,1

Fuente: football-data.co.uk, 2025/26. Cálculo propio.

De los 1.049 equipos que perdían al descanso, el 74,6 % perdió, el 17,1 % empató y el 8,3 % ganó; el Aston Villa lo logró cuatro veces. Y el partido con más goles de la temporada fue una remontada que no llegó: el Mönchengladbach perdía 0-5 con el Eintracht Frankfurt al descanso y terminó 4-6. Diez goles, y ni así.

Ventaja de local: el año que se vaciaron los estadios

Entre ligas, la ventaja de jugar en casa cambia mucho:

En LaLiga el local ganó casi el doble de partidos que el visitante % de partidos que ganó cada uno en 2025/26. Lo que falta hasta 100 son empates.
LigaGana el localGana el visitante
LaLiga48,926,6
Ligue 146,129,4
Bundesliga43,831,7
Premier League42,630,0
Serie A38,935,0

Fuente: football-data.co.uk, 2025/26. Cálculo propio.

¿Por qué pesa tanto jugar en casa en LaLiga y tan poco en la Serie A? Con estos datos no lo sabés. Para aislar al público, el fútbol tuvo un experimento que nadie pidió. Según un estudio publicado en PeerJ, en 2020/21 se jugó a puerta cerrada el 90,7 % de los 3.898 partidos de primera y segunda división de estos cinco países.5

Sin público, la ventaja de local tocó su mínimo % de partidos ganados por el local y por el visitante. Cinco grandes ligas, 2014/15 a 2025/26.
TemporadaGana el localGana el visitante
2014/1545,029,1
2015/1644,429,7
2016/1748,628,3
2017/1845,330,2
2018/1944,729,4
2019/2044,131,5
2020/2139,934,7
2021/2242,831,4
2022/2345,730,0
2023/2443,130,5
2024/2542,033,0
2025/2644,030,5

Fuente: football-data.co.uk, 21.589 partidos. Cálculo propio. 2019/20 mezcla partidos con y sin público.

En las cinco temporadas anteriores, el local ganaba el 45,6 % y el visitante, el 29,3 %. En 2020/21 quedó 39,9 % contra 34,7 %, y en la Premier los visitantes ganaron más partidos que los locales: 153 contra 144. El estudio de PeerJ concluye lo mismo: sin público la ventaja bajó, aunque no desapareció.5

El matiz: en 2024/25, con estadios llenos, la diferencia de goles a favor del local (0,17 por partido) fue casi tan baja como en 2020/21 (0,15). Una temporada sola se mueve mucho por azar; convence que muestras distintas cuenten lo mismo.

Python · ventaja de local por temporada y gráfico
import matplotlib.pyplot as plt

temporadas = ["1415", "1516", "1617", "1718", "1819", "1920",
              "2021", "2122", "2223", "2324", "2425", "2526"]
hist = pd.concat([cargar(t).assign(temporada=t) for t in temporadas])
serie = (hist.groupby("temporada")["FTR"]
             .value_counts(normalize=True).unstack().mul(100).round(1))
print(serie.loc[["1819", "2021", "2526"], ["H", "A"]])

ax = serie[["H", "A"]].plot(marker="o", figsize=(8, 4))
ax.axvspan(5.5, 6.5, alpha=0.15)          # 2020/21, estadios vacíos
ax.set_ylabel("% de partidos")
ax.legend(["Gana el local", "Gana el visitante"])
plt.tight_layout()
plt.savefig("ventaja_local.png", dpi=200)
1819 44.7 29.4
2021 39.9 34.7
2526 44.0 30.5

Dato curioso o historia falsa: el árbitro goleador

Este es el dato que más rápido se comparte y el que más rápido engaña. En la Premier 2025/26, entre los 17 árbitros con diez partidos o más, Salisbury promedió 3,57 goles por partido y Harrington, 2,09. Dos maneras de contarlo:

Premier League 2025/26
Árbitros con 10 partidos o más: 17

Más goles por partido:  Salisbury    3,57  (14 partidos)
Menos goles:            Harrington   2,09  (11 partidos)
Media de la liga:                    2,75

Describe qué pasó, con la muestra y una comparación. No dice por qué.

«Salisbury deja jugar: con él llueven los goles.
Con Harrington, partido trabado.»

Inventa una causa, y el sorteo de abajo muestra que el azar alcanza para fabricar esa diferencia.

Los árbitros no eligen sus partidos, y con 14 u 11 partidos el promedio baila mucho. ¿Cuánto? Repartí los goles de cada partido al azar entre los mismos árbitros, cada uno con su número de partidos, y mirá cuánto promedia el más goleador. Diez mil veces.

Python · la prueba del sorteo
import numpy as np

pl = df[df["liga"] == "Premier League"]
arb = pl.groupby("Referee")["goles"].agg(["size", "mean"])
arb = arb[arb["size"] >= 10]                # al menos 10 partidos
real = arb["mean"].max()                    # 3,57

rng = np.random.default_rng(2026)
maximos = []
for _ in range(10_000):
    goles = pd.Series(rng.permutation(pl["goles"].to_numpy()))
    medias = goles.groupby(pl["Referee"].to_numpy()).mean()
    maximos.append(medias[arb.index].max())

maximos = np.array(maximos)
print(f"{np.median(maximos):.2f} {(maximos >= real).mean() * 100:.1f}")
3.40 23.3

La mediana de esos máximos es 3,40, y el 23,3 % de los sorteos llega a 3,57 o más. O sea, la pura lotería fabrica un «Salisbury» casi una vez de cada cuatro. Ojo, que el sorteo tampoco demuestra que los árbitros no influyan: dice que estos datos no alcanzan para verlo.

Esa es la prueba del sorteo: antes de explicar por qué un grupo se ve distinto (un árbitro, un estadio, los partidos del lunes), repartí los partidos al azar. Si el sorteo produce diferencias parecidas, quedate con el dato y guardá la historia. Y si tenés que contarlo a alguien que no lee código, mirá cómo presentar resultados a un CEO que no entiende de datos.

Antes de publicar tu dato

Pasá cada cifra por esta lista antes de mandarla al grupo de amigos.

● Autodiagnóstico6 controles

¿Tu dato curioso aguanta una discusión?

0 / 6

Antes de contar por qué pasó algo, comprobá que no lo explique un sorteo.

Preguntas frecuentes

¿Dónde descargo datos de fútbol gratis para analizar con Python?

football-data.co.uk publica en CSV los resultados de las grandes ligas europeas desde 1993/94, con marcador al descanso, estadísticas por partido y, en la Premier, el árbitro. El uso gratuito es para particulares. Para datos de cada pase y cada tiro, StatsBomb tiene datos abiertos en GitHub, con la condición de citarlo como fuente.

¿Qué librerías de Python se usan para analizar datos de fútbol?

Para resultados como estos alcanza con pandas para cargar, validar y agrupar, numpy para los sorteos y matplotlib para los gráficos. Con datos de eventos se suman librerías para dibujar canchas, pero casi todo el trabajo sigue siendo pandas: limpiar, unir tablas y comparar grupos.

¿Puedo calcular el xG con estos datos?

No. El xG, o goles esperados, estima la probabilidad de gol de cada tiro según desde dónde y cómo se hizo, y eso exige datos de cada disparo. football-data solo trae tiros totales y a puerta por partido. Para practicar xG, usá los datos abiertos de StatsBomb.

¿Quién es Mister Chip?

Es Alexis Martín-Tamayo, comentarista deportivo nacido en Badajoz e ingeniero de telecomunicación por la Universidad de Sevilla. Según su biografía en ESPN, trabaja con esa cadena desde 2017 y es uno de los comunicadores deportivos más reconocidos en redes sociales, famoso por la rapidez con la que reúne datos.

Fuentes

  1. Football-Data.co.uk. Historical Football Results and Betting Odds Data. Archivos de 2014/15 a 2025/26 de las cinco grandes ligas, descargados el 4 de octubre de 2026.
  2. Football-Data.co.uk. Notes for Football Data (clave de columnas).
  3. ESPN Press Room. Alexis Martín-Tamayo (Mr. Chip).
  4. Bundesliga. DFB rules in favour of Bochum win at Union Berlin. 28 de abril de 2025.
  5. Sors, F., Grassi, M., Agostini, T. y Murgia, M. A complete season with attendance restrictions confirms the relevant contribution of spectators to home advantage and referee bias in association football. PeerJ, 10, e13681, 2022.
  6. Wikipedia. Temporada 2025/26 de Premier League, LaLiga, Serie A, Bundesliga y Ligue 1, consultadas el 4 de octubre de 2026.
  7. StatsBomb. StatsBomb Open Data.