O que é uma “zebra”?

Zebra, no esporte, é um jargão usado para se referir a um resultado improvável do ponto de vista do esperado. Quando um time teoricamente mais fraco ganha de um considerado mais forte, quando um esportista individual vence outro melhor colocado em um ranking, etc.

No universo das apostas, as zebras são muito valiosas e almejadas, pois caso o apostador acerte a ocorrência de uma, será recompensado com ganhos elevados em relação ao valor apostado.

Aqui trataremos da possibilidade de prevermos uma zebra em um jogo de Copa do Mundo. É um tanto difícil por duas razões:

Para tentarmos eliminar a subjetividade, usaremos o ranking da FIFA de seleções.

Sim, eu sei que o ranking é objeto de controvérsia, tendo em vista sua inconsistência em relação à realidade do futebol. A Argentina foi recentemente campeã da Copa do Mundo, o torneio de maior peso de todo o futebol, e não se encontra na primeira posição no ranking (na data desse estudo), o que explicita uma grande falha metodológica.

Mas se vamos entrar nesse tipo de comparação e almejamos eliminar a subjetividade para o estudo, que pelo menos tenhamos uma base razoavelmente concreta para avançar nesse sentido.

Tiramos a média anual do ranking FIFA da seleção no ano da partida e criamos as variáveis onde temos o ranking do time e de seu oponente, e calculamos a diferença entre os dois dados.

As premissas para considerar uma zebra no nosso estudo são as seguintes:

Com isso, vamos ao nosso código.

Carregamento do dataset, englobando jogos de 2002 a 2022.

library(readr)
library(caret)
## Carregando pacotes exigidos: ggplot2
## Carregando pacotes exigidos: lattice
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(rpart)
library(corrplot)
## corrplot 0.92 loaded
dataset_copa2002_2022 <- read_csv("dataset_copa2002-2022.csv", show_col_types = FALSE)

dataset_zebra <- dataset_copa2002_2022 %>%
  select(ano_copa, id_jogo, time, mandante, oponente, vitoria, empate, derrota, ranking_fifa_time, ranking_fifa_oponente, diferenca_ranking, zebra)

head(dataset_zebra)

Dataset de treino e teste

Para treinar o modelo vamos considerar apenas os dados dos jogos de 2002 a 2018, e usaremos os jogos de 2022 para compararmos os nossos resultados obtidos pelo modelo com a realidade ocorrida.

Canadá, País de Gales e Catar, participantes da edição de 2022, serão removidos do dataset de teste, pois como não possuem histórico no período do dataset que temos, causariam erros na geração da nossa predição.

dataset_treino <- dataset_zebra %>%
  filter(ano_copa < 2022)

dataset_teste <- dataset_zebra %>%
  filter(ano_copa == 2022 & 
           mandante == 1 &
           !(time %in% c('Qatar', 'Canada', 'Wales')) &
           !(oponente %in% c('Qatar', 'Canada', 'Wales')))

Descoberta de Correlações

matriz_correlacao <- dataset_zebra %>%
  select(c(6:12))

corrplot(cor(matriz_correlacao, use = "complete.obs"), 
         type = "lower", 
         diag = FALSE)

Curiosamente, o plot mostra uma correlação bastante significativa entre os empates e zebras. Podemos partir da premissa que o empate seria o tipo mais fácil de zebras, haja vista que o time mais limitado pode:

Os times que mais empatam são mais propensos a causarem zebras? É uma hipótese a validar com outros estudos. Para fins de construção do nosso modelo, vamos usar a variável.

Modelo usado

Vamos usar a árvore de decisões para criação do

modelo_zebra <- rpart(zebra ~ time + mandante + oponente + empate, 
                      data = dataset_treino)

Resultados

resultados_zebra <- cbind(dataset_teste, predicao_zebra = ifelse(predict(modelo_zebra, newdata = dataset_teste) > 0.5, 1, 0))

resultados_zebra <- resultados_zebra %>%
  select(time, oponente, zebra, predicao_zebra) %>%
  arrange(desc(predicao_zebra)) %>%
  as_tibble()

print(resultados_zebra)
## # A tibble: 55 × 4
##    time      oponente      zebra predicao_zebra
##    <chr>     <chr>         <dbl>          <dbl>
##  1 Mexico    Poland            1              1
##  2 Morocco   Croatia           0              1
##  3 Uruguay   South Korea       1              1
##  4 England   United States     1              1
##  5 Spain     Germany           1              1
##  6 Cameroon  Serbia            1              1
##  7 Morocco   Spain             1              1
##  8 England   Iran              0              0
##  9 Senegal   Netherlands       0              0
## 10 Argentina Saudi Arabia      1              0
## # … with 45 more rows

Validação

matriz_validacao <- table(real = resultados_zebra$zebra,
                          predicao = resultados_zebra$predicao_zebra)

confusionMatrix(matriz_validacao)
## Confusion Matrix and Statistics
## 
##     predicao
## real  0  1
##    0 30  1
##    1 18  6
##                                           
##                Accuracy : 0.6545          
##                  95% CI : (0.5142, 0.7776)
##     No Information Rate : 0.8727          
##     P-Value [Acc > NIR] : 0.9999930       
##                                           
##                   Kappa : 0.2367          
##                                           
##  Mcnemar's Test P-Value : 0.0002419       
##                                           
##             Sensitivity : 0.6250          
##             Specificity : 0.8571          
##          Pos Pred Value : 0.9677          
##          Neg Pred Value : 0.2500          
##              Prevalence : 0.8727          
##          Detection Rate : 0.5455          
##    Detection Prevalence : 0.5636          
##       Balanced Accuracy : 0.7411          
##                                           
##        'Positive' Class : 0               
## 
print(resultados_zebra[resultados_zebra$zebra == 1 &
                       resultados_zebra$predicao_zebra == 1, ])
## # A tibble: 6 × 4
##   time     oponente      zebra predicao_zebra
##   <chr>    <chr>         <dbl>          <dbl>
## 1 Mexico   Poland            1              1
## 2 Uruguay  South Korea       1              1
## 3 England  United States     1              1
## 4 Spain    Germany           1              1
## 5 Cameroon Serbia            1              1
## 6 Morocco  Spain             1              1

Conseguimos prever corretamente 6 zebras ocorridas na Copa de 2022 usando histórico desses países, conforme a nossa matriz de validação.

É um resultado promissor, tendo em vista a dificuldade de prever algo do gênero.

Em breve vamos pesquisar novas variáveis para introduzir no nosso modelo preditivo de zebras (talvez algo envolvendo as odds de casas de apostas), por enquanto esses são os nossos resultados.