Em época de Copa do Mundo, o mercado de apostas sempre se torna incrivelmente aquecido.
As casas de apostas investem cada vez mais em métodos preditivos para melhorar suas odds, de forma a combinar a atratividade para o apostador e a contenção de eventuais perdas.
Sendo eu mesmo um apostador, criei esse projeto de predição de estatísticas em jogos.
Esse notebook visa criar três modelos para fazer predições sobre os seguintes dados estatísticos de jogos de futebol da Copa do Mundo.
Cartões amarelos
Escanteios
Primeiro time a marcar o gol
Usaremos os seguintes pacotes R
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(readr)
library(corrplot)
## corrplot 0.92 loaded
Carrega o dataset, cria o vetor com os times da edição e filtra os times participantes da Copa do Mundo de 2022
dataset_estatisticas_copa <- read_csv("dataset_copa2010-2022.csv", show_col_types = FALSE)
paises_2022 <- unique(dataset_estatisticas_copa$time[dataset_estatisticas_copa$ano_copa == 2022])
dataset_treino <- dataset_estatisticas_copa %>%
filter(time %in% paises_2022)
O dataset usado possui dados de jogos desde a Copa de 2010. Pode eventualmente haver alguma irregularidade de dados, pois o dataset recebeu algumas intervenções manuais, mas nada que implique em prejuízos ao trabalho.
Para selecionarmos as melhores variáveis para integrar os nossos
modelos de regressão, é apropriado usarmos corrplot para
verificarmos as correlações entre os dados
matriz_estatisticas <- dataset_estatisticas_copa %>%
select(12, c(15:23)) %>%
as.matrix()
correlacao_matriz <- cor(matriz_estatisticas, use = "complete.obs", method = "pearson")
corrplot(correlacao_matriz,
diag = FALSE, method = 'circle', type = "lower")
Como podemos observar no plot, há uma correlação direta, significativa e embasada na lógica entre:
Cartões amarelos e quantidade de faltas (faz sentido, pois o maior fator gerador de cartões são as faltas);
Escanteios a favor e posse de bola, chutes e chutes a gol (faz sentido, pois para gerar escanteios o time precisa ter a bola, finalizar e alvejar o gol);
Abertura do placar com precisão dos chutes (dado obtido dividindo chutes no gol pelo total de chutes) e chutes no gol (faz sentido, pois para marcar o primeiro gol é preciso investir em tentativas de finalização e acertar o gol).
Com base nisso, vamos criar os modelos de regressão com fórmulas que incluam essas variáveis.
Usaremos a regressão de Poisson, pois estamos tratando de dados obtidos numa janela de tempo específica (90 minutos de jogo) e independentes entre os eventos (um dado de um time em determinado jogo não influencia no próximo jogo desse time, pelo menos não no âmbito da teoria estatística).
modelo_amarelos <- glm(cartoes_amarelos ~ time + faltas_cometidas,
data = dataset_treino, family = "poisson")
modelo_escanteios <- glm(escanteios_afavor ~ time + posse_bola + chutes_gol + chutes,
data = dataset_treino, family = "poisson")
Para esse modelo usaremos a regressão logística, pelo fato da variável alvo ser binária (sim ou não, simbolizada por 1 e 0).
modelo_primeiro_gol <- glm(abriu_placar ~ time + chutes_gol + precisao_chute,
data = dataset_treino, family = "binomial")
Quais dados passaremos para o modelo nos entregar predições para cartões amarelos, escanteios e quem marca o primeiro gol?
Optaremos por criar datasets de teste com dados que representem a média de cada dado pra cada time, de acordo com os dados do dataset de treino.
Parece ser algo apropriado na minha concepção, mas você pode modificar o código para o mínimo, máximo ou mesmo criar esse dataset com dados da sua preferência.
dataset_teste_amarelos <- dataset_treino %>%
group_by(time) %>%
summarise(faltas_cometidas = mean(faltas_cometidas, na.rm = TRUE))
print(dataset_teste_amarelos)
## # A tibble: 32 × 2
## time faltas_cometidas
## <chr> <dbl>
## 1 Argentina 13
## 2 Australia 15.3
## 3 Belgium 14
## 4 Brazil 14.0
## 5 Cameroon 13.7
## 6 Canada 11
## 7 Costa Rica 14.5
## 8 Croatia 14.2
## 9 Denmark 13.6
## 10 Ecuador 15
## # … with 22 more rows
dataset_teste_escanteios <- dataset_treino %>%
group_by(time) %>%
summarise(posse_bola = mean(posse_bola, na.rm = TRUE),
chutes_gol = mean(chutes_gol, na.rm = TRUE),
chutes = mean(chutes, na.rm = TRUE))
print(dataset_teste_escanteios)
## # A tibble: 32 × 4
## time posse_bola chutes_gol chutes
## <chr> <dbl> <dbl> <dbl>
## 1 Argentina 58.1 6.52 13.3
## 2 Australia 44.8 3.08 7.85
## 3 Belgium 53.8 6.47 13.3
## 4 Brazil 55.8 7.55 15.9
## 5 Cameroon 47.7 4.33 10.9
## 6 Canada 52 1.33 11.3
## 7 Costa Rica 37.9 3 6.55
## 8 Croatia 54.6 4.71 12.3
## 9 Denmark 49 4.5 10.3
## 10 Ecuador 50.5 3.67 9.5
## # … with 22 more rows
dataset_teste_primeiro_gol <- dataset_treino %>%
group_by(time) %>%
summarise(chutes_gol = mean(chutes_gol, na.rm = TRUE),
precisao_chute = mean(precisao_chute, na.rm = TRUE))
print(dataset_teste_primeiro_gol)
## # A tibble: 32 × 3
## time chutes_gol precisao_chute
## <chr> <dbl> <dbl>
## 1 Argentina 6.52 0.503
## 2 Australia 3.08 0.370
## 3 Belgium 6.47 0.478
## 4 Brazil 7.55 0.482
## 5 Cameroon 4.33 0.392
## 6 Canada 1.33 0.115
## 7 Costa Rica 3 0.434
## 8 Croatia 4.71 0.368
## 9 Denmark 4.5 0.463
## 10 Ecuador 3.67 0.395
## # … with 22 more rows
Obtemos os resultados usando predict, e montamos o
dataset com os resultados com cbind e
dplyr.
resultados_amarelos <- cbind(dataset_teste_amarelos,
amarelos_previstos = round(predict(modelo_amarelos, newdata = dataset_teste_amarelos, type = "response"), digits = 4))
resultados_amarelos <- resultados_amarelos %>%
select(time, amarelos_previstos) %>%
arrange(desc(amarelos_previstos)) %>%
as_tibble()
print(resultados_amarelos)
## # A tibble: 32 × 2
## time amarelos_previstos
## <chr> <dbl>
## 1 Serbia 3.28
## 2 Canada 2.59
## 3 Saudi Arabia 2.39
## 4 Qatar 2.28
## 5 Netherlands 2.23
## 6 Ghana 2.20
## 7 Mexico 2.09
## 8 Australia 2.01
## 9 Iran 1.99
## 10 Costa Rica 1.98
## # … with 22 more rows
resultados_escanteios <- cbind(dataset_teste_escanteios,
escanteios_previstos = round(predict(modelo_escanteios, newdata = dataset_teste_escanteios, type = "response"), digits = 4))
resultados_escanteios <- resultados_escanteios %>%
select(time, escanteios_previstos) %>%
arrange(desc(escanteios_previstos)) %>%
as_tibble()
print(resultados_escanteios)
## # A tibble: 32 × 2
## time escanteios_previstos
## <chr> <dbl>
## 1 Brazil 6.81
## 2 Spain 6.36
## 3 England 6.19
## 4 Germany 6.08
## 5 Belgium 6.07
## 6 Argentina 5.89
## 7 South Korea 5.15
## 8 Portugal 5.11
## 9 Croatia 5.03
## 10 Tunisia 4.91
## # … with 22 more rows
resultados_primeiro_gol <- cbind(dataset_teste_primeiro_gol,
chance_primeiro_gol_prevista = round(predict(modelo_primeiro_gol, newdata = dataset_teste_primeiro_gol, type = "response"), digits = 4))
resultados_primeiro_gol <- resultados_primeiro_gol %>%
select(time, chance_primeiro_gol_prevista) %>%
arrange(desc(chance_primeiro_gol_prevista)) %>%
as_tibble()
print(resultados_primeiro_gol)
## # A tibble: 32 × 2
## time chance_primeiro_gol_prevista
## <chr> <dbl>
## 1 Argentina 0.799
## 2 Spain 0.730
## 3 Brazil 0.689
## 4 Portugal 0.630
## 5 Germany 0.605
## 6 France 0.600
## 7 Uruguay 0.581
## 8 Senegal 0.578
## 9 Belgium 0.534
## 10 Netherlands 0.531
## # … with 22 more rows
Algumas interpretações dos nossos resultados:
Sérvia, Canadá e Arábia Saudita são os três times com maior número de cartões amarelos possíveis em um jogo, enquanto Espanha, Inglaterra e Alemanha estão no outro espectro.
Brasil, Espanha e Inglaterra lideram o número de escanteios previstos, enquanto País de Gales, Marrocos e Costa Rica são os times de menor incidência possível de escanteios.
Argentina, Espanha e Brasil lideram o ranking da possibilidade de fazer o primeiro gol em uma partida, enquanto País de Gales, Arábia Saudita e Tunísia são os times com menos chance de abrir o placar.
Fazer predições de Copa do Mundo possui alguns aspectos pecualiares em comparação a ligas nacionais.
Como o universo dos times participantes varia em cada edição com as eliminatórias regionais, os dados históricos disponíveis dos times em Copas varia consideravelmente, culminando em times com mais e menos dados disponíveis.
Esse fator é observado especialmente com o Brasil, que até hoje foi o único país a jogar todas as edições, e também com País de Gales e Canadá, que raramente participam do torneio.
No entanto, temos aqui um estudo que nos entrega predições interessantes para estratégias de apostas, análises esportivas ou mesmo o puro estudo de estatística e ciência de dados aplicada ao esporte.
Sinta-se livre para modificar o código ou tomá-lo como inspiração para criar o seu próprio projeto. Até a próxima!