Como combinei dados reais da fase de grupos com histórico e ranking FIFA para ranquear os favoritos — e o que os números dizem sobre Brasil, Argentina e França
Toda Copa do Mundo traz a mesma pergunta: quem vai ganhar?
A maioria das respostas vem de palpite, torcida ou memória afetiva. Resolvi fazer diferente. Neste artigo, vou mostrar passo a passo como construí um índice composto usando dados reais da competição — e como você pode reproduzir (ou questionar) cada decisão que tomei.
Spoiler: a matemática coloca Argentina e França numa classe à parte. Mas o Brasil tem um argumento histórico que nenhum outro time consegue igualar.
O Problema: por que não usar só a tabela de pontos?
A primeira ideia óbvia é olhar para quem está liderando o grupo. Mas isso tem um problema sério: a fase de grupos não é equilibrada.
Um time pode ter 9 pontos enfrentando adversários fracos, enquanto outro tem 6 pontos num grupo muito difícil. Além disso, a Copa não termina na fase de grupos — e títulos mundiais não aparecem em nenhuma tabela de classificação.
Precisamos de um índice que capture três coisas ao mesmo tempo:
- Forma atual — como o time está jogando agora
- Qualidade do elenco — o quanto ele é tecnicamente superior
- DNA de campeão — histórico de desempenho e conquistas em Copas
As 5 Dimensões do Índice
Depois de testar algumas combinações, cheguei a 5 variáveis com pesos distintos:
| Dimensão | Variável | Peso |
|---|---|---|
| Forma atual | Aproveitamento na fase de grupos | 35% |
| Equilíbrio tático | Eficiência gols pró / gols contra | 20% |
| Tradição | Histórico em Copas do Mundo | 20% |
| Conquistas | Número de títulos mundiais | 15% |
| Qualidade | Ranking FIFA atual | 10% |
Por que esses pesos?
35% para aproveitamento porque a forma atual é o dado mais fresco e direto que temos. Um time que venceu os 3 jogos está tecnicamente em melhor momento do que um que empatou dois.
20% para eficiência porque marcar muitos gols não adianta se você também toma muitos. A proporção gols pró / (gols pró + gols contra) mede equilíbrio entre ataque e defesa de forma mais honesta do que o saldo de gols isolado.
20% para histórico porque Copa do Mundo é um torneio de pressão extrema. Times com tradição de semifinal e final tendem a performar melhor nas fases decisivas — é algo difícil de quantificar, mas impossível de ignorar.
15% para títulos porque há uma diferença real entre ter conquistado a Copa e nunca ter chegado lá. Normalizei pelo máximo possível (5, que é o Brasil).
10% para ranking FIFA porque o ranking captura a qualidade média do elenco ao longo do tempo, não só os últimos 3 jogos.
O Código
Toda a lógica cabe em uma função:
def calc_score(time: dict) -> float:
# Aproveitamento: pontos obtidos sobre máximo possível (9)
aproveitamento = time["pts"] / 9
# Eficiência: proporção do total de gols que foram marcados pelo time
eficiencia = time["gp"] / max(time["gp"] + time["gc"], 1)
# Histórico: normalizado de 0 a 1 (entrada: 0–100)
historico = time["historico"] / 100
# Títulos: normalizado pelo máximo histórico (5 = Brasil)
titulos = min(time["titulos"] / 5, 1)
# Ranking FIFA: invertido (rank 1 = melhor) e normalizado
rank = (10 - min(time["rank_fifa"], 10)) / 9
return (
aproveitamento * 35 +
eficiencia * 20 +
historico * 20 +
titulos * 15 +
rank * 10
)
Simples, sem biblioteca, sem magia. Cada linha tem uma justificativa clara.
Os Dados de Entrada
Coletei os dados reais da fase de grupos via SportRadar em 29/06/2026. Os dados históricos são referência pública do ranking FIFA e do acervo de títulos de cada seleção.
FAVORITOS = [
{"nome": "Argentina", "pts": 9, "gp": 9, "gc": 2, "v": 3, "e": 0, "d": 0,
"titulos": 3, "rank_fifa": 1, "historico": 95},
{"nome": "França", "pts": 9, "gp": 9, "gc": 2, "v": 3, "e": 0, "d": 0,
"titulos": 2, "rank_fifa": 2, "historico": 88},
{"nome": "Brasil", "pts": 7, "gp": 7, "gc": 3, "v": 2, "e": 1, "d": 0,
"titulos": 5, "rank_fifa": 5, "historico": 92},
{"nome": "Espanha", "pts": 7, "gp": 8, "gc": 2, "v": 2, "e": 1, "d": 0,
"titulos": 1, "rank_fifa": 3, "historico": 82},
{"nome": "Alemanha", "pts": 6, "gp": 7, "gc": 4, "v": 2, "e": 0, "d": 1,
"titulos": 4, "rank_fifa": 4, "historico": 85},
{"nome": "Inglaterra", "pts": 7, "gp": 6, "gc": 2, "v": 2, "e": 1, "d": 0,
"titulos": 1, "rank_fifa": 6, "historico": 75},
{"nome": "Portugal", "pts": 5, "gp": 4, "gc": 3, "v": 1, "e": 2, "d": 0,
"titulos": 0, "rank_fifa": 7, "historico": 70},
{"nome": "Holanda", "pts": 7, "gp": 6, "gc": 2, "v": 2, "e": 1, "d": 0,
"titulos": 0, "rank_fifa": 8, "historico": 72},
]
A variável historico é uma métrica composta que criei manualmente, baseada em presença em finais, semifinais e títulos nos últimos 40 anos, normalizada de 0 a 100. É a parte mais subjetiva do modelo — e é justo assumir isso.
Calculando e Ordenando
# Calcula o score de cada time e ordena do maior para o menor
ranking = sorted(
[{**t, "score": calc_score(t)} for t in FAVORITOS],
key=lambda t: t["score"],
reverse=True
)
max_score = ranking[0]["score"]
# Normaliza para um índice de 0–100%
ranking_final = [
{**t, "indice": round((t["score"] / max_score) * 100, 1)}
for t in ranking
]
Normalizar pelo maior score transforma o resultado em um índice relativo: o favorito vira 100% e os outros ficam proporcionais a ele. Isso é mais fácil de comunicar do que um número bruto como "86.4".
Os Resultados
Aplicando a fórmula nos dados de 29/06/2026:
🇦🇷 Argentina ████████████████████████████████████████ 100.0%
🇫🇷 França ████████████████████████████████████████ 97.3%
🇧🇷 Brasil ████████████████████████████████████ 91.3%
🇪🇸 Espanha ███████████████████████████████████ 87.0%
🇩🇪 Alemanha █████████████████████████████████ 83.1%
🏴 Inglaterra ███████████████████████████████ 77.8%
🇳🇱 Holanda ████████████████████████████████ 79.3%
🇵🇹 Portugal ████████████████████████████ 69.6%
Lendo os números
Argentina (100%) — campanha perfeita: 9 pontos, 9 gols marcados, 2 sofridos, saldo de +7, ranking FIFA #1. O único "custo" no índice é ter menos títulos históricos que Brasil e Alemanha.
França (97.3%) — praticamente empatada com a Argentina nos dados da fase de grupos. O que separa as duas é o menor número de títulos (2 contra 3) e o histórico ligeiramente inferior. Na prática, estão em nível igual.
Brasil (91.3%) — o peso histórico salva o Brasil de uma posição mais baixa. Com aproveitamento de 77.8% (inferior aos dois primeiros) e 3 gols sofridos, a campanha atual não é a mais dominante. Mas 5 títulos e um historico: 92 puxam o score para cima.
Espanha (87%) — o dado mais surpreendente positivo. Melhor saldo de gols entre todos os favoritos (8 pró, 2 contra), mas penalizada pelo menor número de títulos (1) e ranking FIFA #3.
Alemanha (83.1%) — 4 títulos mundiais garantem uma base histórica forte, mas a única derrota na fase de grupos e os 4 gols sofridos puxam o score para baixo.
O Que o Modelo Não Captura
Toda análise estatística tem limites. Ser transparente sobre eles é parte do trabalho.
Este índice não considera:
Chaveamento do mata-mata — um sorteio favorável ou desfavorável pode redefinir tudo. Uma Argentina que pega Portugal nas quartas enfrenta desafio muito diferente de uma que pega Marrocos.
Lesões — o dado de hoje pode ser inútil amanhã. Um jogador-chave fora muda o time completamente.
Forma individual — Messi em grande fase vale mais do que qualquer número no modelo. Estatística agregada não captura picos de performance individual.
Pênaltis — a Inglaterra sabe bem o que acontece quando o jogo vai para a loteria das penalidades. Não existe variável histórica boa o suficiente para prever isso.
Pressão psicológica — times que nunca ganharam uma Copa podem travar em decisões. Isso aparece parcialmente no
historico, mas de forma imperfeita.
Como Você Pode Melhorar Esse Modelo
Se quiser ir além, aqui estão algumas extensões possíveis:
1. Simular o chaveamento
Em vez de só calcular um índice, você pode simular os confrontos do mata-mata com probabilidades baseadas no score de cada time. Monte Carlo com 10.000 simulações daria uma distribuição de chances de título.
import random
def simular_copa(times: list, simulacoes: int = 10000) -> list:
vitorias = {t["nome"]: 0 for t in times}
for _ in range(simulacoes):
campeao = simular_mata_mata(times) # sua lógica aqui
vitorias[campeao] += 1
return sorted(
[{"nome": nome, "prob": round(v / simulacoes * 100, 1)}
for nome, v in vitorias.items()],
key=lambda x: x["prob"],
reverse=True
)
2. Adicionar dados de jogadores
Integrar dados individuais (gols, assistências, minutos jogados) para criar um score de elenco mais granular, em vez de usar apenas o ranking FIFA.
3. Atualizar em tempo real
Conectar a uma API de dados esportivos e recalcular o índice após cada jogo. O score muda a cada resultado — e a Copa ainda tem muitos jogos pela frente.
4. Ajustar pesos com machine learning
Se você tiver dados históricos de Copas anteriores, pode usar regressão logística para aprender os pesos ótimos em vez de defini-los manualmente.
Conclusão
Com os dados disponíveis em 29/06/2026, Argentina e França são as seleções em melhor forma — campanhas perfeitas, defesas sólidas e histórico de alto nível. O Brasil aparece em terceiro, sustentado pelo maior acervo de títulos da história, mas com margem para melhorar na fase eliminatória.
O modelo é simples por design. Não porque o problema é simples — Copa do Mundo é caótica por natureza — mas porque modelos simples e transparentes são mais honestos do que caixas-pretas sofisticadas que fingem certeza onde não existe nenhuma.
A estatística aqui é uma lente. Quem decide o campeonato ainda é o futebol.
Código Completo
O dashboard interativo com todos os dados está disponível em HTML puro, sem frameworks — basta abrir no navegador.
Dados coletados via SportRadar · 29/06/2026
Tags: #python #datascience #futebol #copa2026 #estatistica #worldcup
Top comments (0)