projects 18.06.26 · 13 MIN

Mundial 2026 — Actualización del 18 de junio: 24 partidos jugados, modelo refrescado

Ya van 24 partidos de la fase de grupos. Capturé todos los resultados reales hasta hoy desde football-data.org, reentrené el modelo bayesiano con esos datos, y volví a simular el torneo completo (500 mil veces sobre la GPU) condicionando a lo que ya ocurrió. Aquí está el panorama actualizado: cómo le ha ido al modelo, qué viene —en orden cronológico para que sea fácil de seguir— y cómo quedaron las probabilidades de campeón.

Qué se actualizó en este refresh:

  • 24 resultados reales rellenados en el dataset (jornadas del 11 al 17 de junio).
  • Posterior bayesiano reentrenado (Poisson jerárquico con ataque/defensa por selección + altitud de sede).
  • Predicciones de los 48 partidos restantes regeneradas.
  • Simulación del torneo completo recalculada: los partidos jugados quedan fijos a su marcador, solo se simula lo que falta.

¿Cómo le ha ido al modelo?

Sobre los 24 partidos jugados, el favorito del modelo acertó 14 de 24 (58.3%), con una log-loss de 0.918. La fase de grupos de un Mundial es brutal para cualquier pronosticador: muchos empates inesperados (España 0-0 Cabo Verde, Arabia 1-1 Uruguay, Bélgica 1-1 Egipto) y favoritos que tropiezan. Aun así, los grandes batacazos esperados se cumplieron: Argentina, Francia, Inglaterra y Alemania ganaron con solvencia.

Resultados ya jugados (orden cronológico)

Fecha Partido Resultado Pick del modelo
11 jun México vs Sudáfrica 2-0 México (56%)
11 jun Corea del Sur vs Rep. Checa 2-1 Corea del Sur (48%)
12 jun Canadá vs Bosnia 1-1 Canadá (58%)
12 jun EE.UU. vs Paraguay 4-1 EE.UU. (44%)
13 jun Australia vs Turquía 2-0 Australia (52%)
13 jun Brasil vs Marruecos 1-1 Brasil (35%)
13 jun Haití vs Escocia 0-1 Escocia (50%)
13 jun Qatar vs Suiza 1-1 Suiza (65%)
14 jun Alemania vs Curazao 7-1 Alemania (88%)
14 jun Costa de Marfil vs Ecuador 1-0 Empate (38%)
14 jun P. Bajos vs Japón 2-2 Japón (41%)
14 jun Suecia vs Túnez 5-1 Suecia (46%)
15 jun Bélgica vs Egipto 1-1 Bélgica (44%)
15 jun Irán vs Nueva Zelanda 2-2 Irán (44%)
15 jun Arabia Saudí vs Uruguay 1-1 Uruguay (52%)
15 jun España vs Cabo Verde 0-0 España (72%)
16 jun Argentina vs Argelia 3-0 Argentina (68%)
16 jun Austria vs Jordania 3-1 Austria (52%)
16 jun Francia vs Senegal 3-1 Francia (53%)
16 jun Irak vs Noruega 1-4 Noruega (65%)
17 jun Inglaterra vs Croacia 4-2 Inglaterra (56%)
17 jun Ghana vs Panamá 1-0 Ghana (37%)
17 jun Portugal vs RD Congo 1-1 Portugal (55%)
17 jun Uzbekistán vs Colombia 1-3 Colombia (62%)

La racha del 16 y 17 de junio fue casi perfecta (8 de 9): las potencias por fin jugaron y el modelo brilla cuando hay diferencia clara de nivel. Donde sufre es en los duelos parejos del medio de la tabla, justo donde el fútbol es más impredecible.


¿Quién levanta la copa? (odds actualizadas)

Con los 24 resultados fijados y el resto simulado, así quedan las probabilidades de ser campeón del mundo. Argentina se despega (14.8%) tras su 3-0 a Argelia; España se mantiene segunda pese al tropiezo con Cabo Verde (su grupo sigue siendo accesible). Inglaterra sube fuerte tras el 4-2 a Croacia.

@d3
const data = [{"t":"Argentina","v":14.8},{"t":"España","v":10.9},{"t":"Inglaterra","v":7.3},{"t":"Brasil","v":6.3},{"t":"Francia","v":6.0},{"t":"Colombia","v":5.9},{"t":"Alemania","v":5.7},{"t":"Marruecos","v":4.9},{"t":"Portugal","v":4.5},{"t":"Japón","v":3.5},{"t":"Australia","v":3.4},{"t":"Noruega","v":2.9},{"t":"P. Bajos","v":2.6},{"t":"Uruguay","v":2.4},{"t":"México","v":2.1},{"t":"Bélgica","v":2.0}];
const W = container.clientWidth || 1000;
const m = {top:8,right:64,left:120,bottom:28};
const rowH = 30, H = data.length*rowH + m.top + m.bottom;
const svg = d3.select(container).append('svg').attr('width',W).attr('height',H)
  .attr('font-family','JetBrains Mono, system-ui, sans-serif');
const x = d3.scaleLinear().domain([0, d3.max(data,d=>d.v)*1.08]).range([m.left, W-m.right]);
const y = d3.scaleBand().domain(data.map(d=>d.t)).range([m.top, H-m.bottom]).padding(0.45);
const color = d3.scaleSequential(d3.interpolateTurbo).domain([d3.max(data,d=>d.v)*1.25, 0]);
svg.append('g').attr('transform',`translate(0,${H-m.bottom})`)
  .call(d3.axisBottom(x).ticks(6).tickFormat(d=>d+'%'))
  .call(g=>g.select('.domain').remove())
  .call(g=>g.selectAll('.tick line').attr('stroke','#33332e'))
  .attr('color','#9a9a8e').attr('font-size','11px');
const row = svg.selectAll('g.row').data(data).join('g');
row.append('line').attr('x1',x(0)).attr('x2',d=>x(d.v))
  .attr('y1',d=>y(d.t)+y.bandwidth()/2).attr('y2',d=>y(d.t)+y.bandwidth()/2)
  .attr('stroke',d=>color(d.v)).attr('stroke-width',3).attr('opacity',0.5);
row.append('circle').attr('cx',d=>x(d.v)).attr('cy',d=>y(d.t)+y.bandwidth()/2)
  .attr('r',7).attr('fill',d=>color(d.v));
row.append('text').attr('x',m.left-10).attr('y',d=>y(d.t)+y.bandwidth()/2)
  .attr('dy','0.35em').attr('text-anchor','end').attr('font-size','13px')
  .attr('fill','#d4d4c8').text(d=>d.t);
row.append('text').attr('x',d=>x(d.v)+12).attr('y',d=>y(d.t)+y.bandwidth()/2)
  .attr('dy','0.35em').attr('font-size','12px').attr('font-weight','600')
  .attr('fill',d=>color(d.v)).text(d=>d.v.toFixed(1)+'%');

El camino a la gloria

Cada celda es la probabilidad de alcanzar esa ronda, de izquierda (octavos) a derecha (campeón). Pasa el cursor para el valor exacto.

@plotly
{"data": [{"type": "heatmap", "z": [[46.8,23.2,10.4,4.7,2.0],[56.3,26.8,11.5,5.0,2.1],[34.4,19.3,10.3,5.0,2.4],[42.2,22.1,11.6,5.6,2.6],[54.9,26.6,13.6,6.4,2.9],[59.8,32.9,15.3,7.4,3.4],[45.1,24.9,13.7,7.0,3.5],[52.1,29.6,16.6,8.8,4.5],[53.3,30.5,17.5,9.4,4.9],[62.7,39.9,21.9,11.7,5.7],[65.5,39.9,21.1,11.3,5.9],[64.4,35.8,20.7,11.1,6.0],[57.9,34.7,20.9,11.8,6.3],[65.0,39.5,22.9,12.7,7.3],[59.5,41.0,28.6,18.1,10.9],[68.5,51.5,35.5,22.7,14.8]], "x": ["Octavos","Cuartos","Semis","Final","Campeón"], "y": ["Bélgica","México","Uruguay","P. Bajos","Noruega","Australia","Japón","Portugal","Marruecos","Alemania","Colombia","Francia","Brasil","Inglaterra","España","Argentina"], "colorscale": "YlGnBu", "zmin": 0, "zmax": 75, "xgap": 2, "ygap": 2, "hovertemplate": "%{y}  %{x}: %{z:.1f}%<extra></extra>", "colorbar": {"ticksuffix": "%", "outlinewidth": 0, "tickfont": {"color": "#d4d4c8"}, "thickness": 14}}], "layout": {"height": 520, "margin": {"l": 110, "r": 20, "t": 30, "b": 30}, "paper_bgcolor": "rgba(0,0,0,0)", "plot_bgcolor": "rgba(0,0,0,0)", "font": {"family": "JetBrains Mono, system-ui, sans-serif", "size": 12, "color": "#d4d4c8"}, "xaxis": {"side": "top", "tickfont": {"color": "#d4d4c8"}, "fixedrange": true}, "yaxis": {"tickfont": {"color": "#d4d4c8"}, "fixedrange": true}}}

Tabla completa (top 24)

# Selección Gr Octavos Cuartos Semis Final Campeón
1 Argentina J 68% 52% 36% 23% 14.8%
2 España H 60% 41% 29% 18% 10.9%
3 Inglaterra L 65% 40% 23% 13% 7.3%
4 Brasil C 58% 35% 21% 12% 6.3%
5 Francia I 64% 36% 21% 11% 6.0%
6 Colombia K 66% 40% 21% 11% 5.9%
7 Alemania E 63% 40% 22% 12% 5.7%
8 Marruecos C 53% 30% 18% 9% 4.9%
9 Portugal K 52% 30% 17% 9% 4.5%
10 Japón F 45% 25% 14% 7% 3.5%
11 Australia D 60% 33% 15% 7% 3.4%
12 Noruega I 55% 27% 14% 6% 2.9%
13 P. Bajos F 42% 22% 12% 6% 2.6%
14 Uruguay H 34% 19% 10% 5% 2.4%
15 México A 56% 27% 12% 5% 2.1%
16 Bélgica G 47% 23% 10% 5% 2.0%
17 Suiza B 47% 20% 9% 4% 1.5%
18 Ecuador E 33% 16% 7% 3% 1.4%
19 EE.UU. D 51% 24% 9% 4% 1.3%
20 Corea A 51% 22% 8% 3% 1.3%
21 Austria J 38% 17% 8% 3% 1.1%
22 C. Marfil E 42% 18% 7% 3% 1.0%
23 Croacia L 30% 13% 6% 2% 0.9%
24 Canadá B 38% 14% 6% 2% 0.8%

¿Quién pasa de grupos?

Con 48 equipos y 32 plazas (12 primeros, 12 segundos, 8 mejores terceros), los punteros de cada grupo ya casi tienen el boleto. Probabilidad de avanzar a la ronda de 32:

@vega-lite
{"$schema": "https://vega.github.io/schema/vega-lite/v5.json", "width": "container", "height": 460, "background": "transparent", "data": {"values": [{"team": "Argentina", "p": 99.8}, {"team": "Alemania", "p": 99.7}, {"team": "Inglaterra", "p": 99.6}, {"team": "Francia", "p": 99.2}, {"team": "México", "p": 98.6}, {"team": "Australia", "p": 98.3}, {"team": "Colombia", "p": 97.7}, {"team": "Noruega", "p": 97.5}, {"team": "EE.UU.", "p": 97.3}, {"team": "C. Marfil", "p": 96.3}, {"team": "Corea", "p": 95.6}, {"team": "Brasil", "p": 94.4}, {"team": "Austria", "p": 93.5}, {"team": "Suecia", "p": 92.8}, {"team": "Marruecos", "p": 91.9}, {"team": "España", "p": 90.3}, {"team": "Japón", "p": 88.6}, {"team": "P. Bajos", "p": 87.8}, {"team": "Suiza", "p": 84.5}, {"team": "Escocia", "p": 80.7}]}, "mark": {"type": "bar", "cornerRadiusEnd": 3}, "encoding": {"y": {"field": "team", "type": "nominal", "sort": "-x", "title": null, "axis": {"labelFontSize": 12, "labelColor": "#d4d4c8"}}, "x": {"field": "p", "type": "quantitative", "title": "Probabilidad de avanzar (%)", "scale": {"domain": [0, 100]}, "axis": {"labelColor": "#d4d4c8", "titleColor": "#d4d4c8", "gridColor": "#2a2a26"}}, "color": {"field": "p", "type": "quantitative", "scale": {"scheme": "tealblues"}, "legend": null}, "tooltip": [{"field": "team", "title": "Selección"}, {"field": "p", "title": "% avanza"}]}, "config": {"view": {"stroke": null}, "background": "transparent", "axis": {"domainColor": "#2a2a26"}}}

Lo que viene — predicciones día por día

Los 48 partidos restantes de la fase de grupos, en orden cronológico. Columnas: probabilidades L / E / V (local / empate / visitante, %), marcador más probable y el favorito del modelo. Sede neutral, así que "local" es solo el primer equipo del fixture.

18 jun

Grupo Partido L / E / V Marcador Favorito
B Canadá vs Qatar 58 / 22 / 20 2-1 Canadá
A Rep. Checa vs Sudáfrica 42 / 28 / 30 1-1 Rep. Checa
A México vs Corea del Sur 41 / 31 / 28 1-1 México
B Suiza vs Bosnia 65 / 22 / 14 2-1 Suiza

19 jun

Grupo Partido L / E / V Marcador Favorito
C Brasil vs Haití 77 / 15 / 8 2-1 Brasil
C Escocia vs Marruecos 16 / 29 / 54 1-1 Marruecos
D Turquía vs Paraguay 39 / 27 / 34 1-1 Turquía
D EE.UU. vs Australia 28 / 28 / 44 1-1 Australia

20 jun

Grupo Partido L / E / V Marcador Favorito
E Ecuador vs Curazao 67 / 23 / 10 2-0 Ecuador
E Alemania vs Costa de Marfil 54 / 25 / 21 2-1 Alemania
F P. Bajos vs Suecia 57 / 20 / 22 2-1 P. Bajos
F Túnez vs Japón 14 / 24 / 62 1-2 Japón

21 jun

Grupo Partido L / E / V Marcador Favorito
G Bélgica vs Irán 46 / 26 / 28 1-1 Bélgica
G Nueva Zelanda vs Egipto 32 / 30 / 38 1-1 Egipto
H España vs Arabia Saudí 71 / 20 / 9 2-0 España
H Uruguay vs Cabo Verde 53 / 31 / 15 1-0 Uruguay

22 jun

Grupo Partido L / E / V Marcador Favorito
J Argentina vs Austria 63 / 23 / 14 2-1 Argentina
I Francia vs Irak 69 / 20 / 11 2-1 Francia
J Jordania vs Argelia 28 / 25 / 47 1-2 Argelia
I Noruega vs Senegal 46 / 24 / 30 2-1 Noruega

23 jun

Grupo Partido L / E / V Marcador Favorito
K Colombia vs RD Congo 56 / 28 / 16 1-1 Colombia
L Inglaterra vs Ghana 69 / 20 / 11 2-1 Inglaterra
L Panamá vs Croacia 21 / 23 / 56 1-2 Croacia
K Portugal vs Uzbekistán 59 / 24 / 17 2-1 Portugal

24 jun

Grupo Partido L / E / V Marcador Favorito
B Bosnia vs Qatar 33 / 26 / 41 1-1 Qatar
A Rep. Checa vs México 17 / 28 / 55 1-1 México
C Marruecos vs Haití 70 / 20 / 10 2-1 Marruecos
C Escocia vs Brasil 15 / 24 / 62 1-2 Brasil
A Sudáfrica vs Corea del Sur 20 / 26 / 54 1-2 Corea del Sur
B Suiza vs Canadá 42 / 27 / 31 1-1 Suiza

25 jun

Grupo Partido L / E / V Marcador Favorito
E Curazao vs Costa de Marfil 13 / 22 / 64 1-2 Costa de Marfil
E Ecuador vs Alemania 26 / 29 / 45 1-1 Alemania
F Japón vs Suecia 59 / 21 / 20 2-1 Japón
D Paraguay vs Australia 20 / 30 / 50 1-1 Australia
F Túnez vs P. Bajos 16 / 22 / 62 1-2 P. Bajos
D Turquía vs EE.UU. 31 / 24 / 45 1-2 EE.UU.

26 jun

Grupo Partido L / E / V Marcador Favorito
H Cabo Verde vs Arabia Saudí 31 / 36 / 33 1-1 Empate
G Egipto vs Irán 32 / 31 / 37 1-1 Irán
G Nueva Zelanda vs Bélgica 24 / 23 / 53 1-2 Bélgica
I Noruega vs Francia 29 / 24 / 47 1-2 Francia
I Senegal vs Irak 53 / 26 / 20 1-1 Senegal
H Uruguay vs España 21 / 32 / 47 1-1 España

27 jun

Grupo Partido L / E / V Marcador Favorito
J Argelia vs Austria 32 / 27 / 41 1-1 Austria
K Colombia vs Portugal 38 / 26 / 37 1-1 Colombia
L Croacia vs Ghana 53 / 25 / 22 2-1 Croacia
K RD Congo vs Uzbekistán 33 / 36 / 31 1-1 Empate
J Jordania vs Argentina 7 / 16 / 77 1-2 Argentina
L Panamá vs Inglaterra 10 / 18 / 72 1-2 Inglaterra

Cómo se hizo

Pipeline reproducible vía el CLI del proyecto: captura automática de resultados (football-data.org), reentrenamiento del posterior bayesiano jerárquico (numpyro/NUTS, ~10 s) y simulación del torneo completo en PyTorch/CUDA sobre una RTX 4080 (500 mil torneos en pocos segundos). Cada simulación toma una muestra distinta del posterior, así que la incertidumbre del modelo viaja hasta el resultado final; los desempates de grupo siguen el reglamento FIFA y los empates en eliminatorias se resuelven por penales (50/50). Los partidos jugados quedan fijos a su marcador real.

Disclaimer

Esto es un ejercicio de modelado estadístico, no consejo de apuestas. Las probabilidades reflejan el modelo y los resultados ya ocurridos, no certezas. El fútbol, afortunadamente, se juega.