Configuração inicial

Bibliotecas

Carregamos as seguintes bibliotecas do R para adicionar funcionalidades extras:

Pacote Função
tidyverse Manipulação e visualização de dados
knitr + kableExtra Relatórios dinâmicos e formatação de tabelas
rvest Web scraping (coleta de dados)
performance + lmtest + car Diagnóstico e avaliação de modelos estatísticos
cluster + factoextra Análise de agrupamento e visualização multivariada
corrplot Visualização de matrizes de correlação
ggpubr + patchwork Criação e composição de gráficos com ggplot2

Diretório de trabalho

Definimos o diretório de trabalho:

# Definir diretório de trabalho 
setwd("/home/gf/Scripts/Pele")  
# OU usar caminho relativo ao projeto
#getwd()  # Verificar diretório atual

Introdução

A análise busca responder à pergunta: Messi é realmente o maior artilheiro de todas as Copas? A resposta depende do critério adotado. Este estudo utiliza:

  1. Contagem absoluta (gols totais)
  2. Eficiência por jogo (média de gols)
  3. Longevidade (número de Copas disputadas)
  4. Ranking ponderado (combinação de métricas)
  5. Análise de cluster (agrupamento por perfil de desempenho)

P.S.: considerando o desfecho do torneio, a pergunta perdeu a relevância.

Coleta de dados

Os dados foram extraídos da Lista de artilheiros da Copa do Mundo FIFA – Wikipédia.

# Função para extrair tabelas da página da Wikipédia
# Nota: A página contém duas tabelas principais:
# 1. Lista de artilheiros (todos os tempos)
# 2. Artilheiros por edição
extrair_tabelas_wikipedia <- function(url) {
  page <- read_html(url)
  
  # Extrair todas as tabelas da página
  tabelas <- page %>% 
    html_nodes("table.wikitable.sortable") %>%
    html_table(fill = TRUE)
  
  # Identificar tabelas pelos cabeçalhos
  artilheiros <- NULL
  artilheiros_por_edicao <- NULL
  
  for (tabela in tabelas) {
    cabecalhos <- names(tabela)
    
    if (all(c("Jogador", "Seleção", "Gols") %in% cabecalhos)) {
      artilheiros <- tabela
    }
    
    if (all(c("Ano", "Jogador", "Gols") %in% cabecalhos)) {
      artilheiros_por_edicao <- tabela
    }
  }
  
  if (is.null(artilheiros) || is.null(artilheiros_por_edicao)) {
    stop("Não foi possível extrair as tabelas necessárias.")
  }
  
  return(list(
    artilheiros = artilheiros,
    artilheiros_por_edicao = artilheiros_por_edicao
  ))
}

# Executar scraping
url <- "https://pt.wikipedia.org/wiki/Lista_de_artilheiros_da_Copa_do_Mundo_FIFA"
resultado <- extrair_tabelas_wikipedia(url)

# Acessar cada data frame individualmente
artilheiros <- resultado$artilheiros
artilheiros_por_edicao <- resultado$artilheiros_por_edicao

# Salvar os arquivos .csv
write_csv(artilheiros, "artilheiros.csv")
write_csv(artilheiros_por_edicao, "artilheiros_por_edicao.csv")

Processamento dos dados

# Carregar dados
# artilheiros <- read_csv("artilheiros.csv", show_col_types = FALSE)

# Limpeza e transformação de dados
artilheiros <- artilheiros %>%
  # Corrigir formato decimal (vírgula para ponto)
  mutate(
    Média = as.numeric(gsub(",", ".", Média)),
    Gols = as.numeric(Gols),
    Jogos = as.numeric(Jogos)
  ) %>%
  # Calcular variáveis derivadas
  mutate(
    # n_copas: conta o número de torneios separados por vírgula + 1
    n_copas = str_count(Torneios, ",") + 1,
    gols_por_copa = Gols / n_copas,
    jogos_por_copa = Jogos / n_copas
  ) %>%
  # Remover linhas com NA
  drop_na(Gols, Jogos, Média)

# Primeiros registros
kable(
  artilheiros %>%
    select(Jogador, Seleção, Gols, Jogos, Média, n_copas) %>%
    head(10),
  caption = "Primeiros 10 artilheiros da Copa do Mundo",
  format = "html",
  booktabs = TRUE
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Primeiros 10 artilheiros da Copa do Mundo
Jogador Seleção Gols Jogos Média n_copas
Kylian Mbappé França 22 22 1.00 3
Lionel Messi Argentina 21 34 0.61 6
Miroslav Klose Alemanha 16 24 0.67 4
Ronaldo Brasil 15 19 0.79 4
Gerd Müller Alemanha Ocidental 14 13 1.08 2
Harry Kane Inglaterra 14 18 0.77 3
Just Fontaine França 13 6 2.17 1
Pelé Brasil 12 14 0.86 4
Sándor Kocsis Hungria 11 5 2.20 1
Jürgen Klinsmann Alemanha 11 17 0.65 3

Metodologia

Definição de contagem

A contagem, enquanto operação lógica elementar, atribui números absolutos às quantidades observadas — neste caso, o total de gols convertidos em edições do torneio. A média de gols por jogo, por sua vez, normaliza o desempenho pelo número de partidas disputadas, oferecendo um indicador de produtividade.

Critérios de análise

Este estudo adota cinco abordagens complementares:

  1. Contagem absoluta – total de gols, critério tradicional;
  2. Eficiência por jogo – média de gols por partida;
  3. Longevidade – número de Copas disputadas;
  4. Ranking ponderado – combinação normalizada de múltiplas métricas;
  5. Análise de cluster – agrupamento não supervisionado por perfil de desempenho.

A combinação dessas perspectivas permite uma avaliação mais adequada do desempenho dos artilheiros.

Análise descritiva

Estatísticas básicas

# Calcular estatísticas descritivas
stats_gerais <- artilheiros %>%
  summarise(
    `Total de jogadores` = n(),
    `Média de gols` = round(mean(Gols, na.rm = TRUE), 2),
    `Mediana de gols` = round(median(Gols, na.rm = TRUE), 1),
    `Máximo de gols` = max(Gols, na.rm = TRUE),
    `Desvio padrão (gols)` = round(sd(Gols, na.rm = TRUE), 2),
    `Média de jogos` = round(mean(Jogos, na.rm = TRUE), 2),
    `Média de Copas` = round(mean(n_copas, na.rm = TRUE), 2),
    `Máximo de Copas` = max(n_copas, na.rm = TRUE)
  ) %>%
  pivot_longer(everything(), names_to = "Métrica", values_to = "Valor")

kable(stats_gerais, caption = "Estatísticas descritivas da base de dados")
Estatísticas descritivas da base de dados
Métrica Valor
Total de jogadores 72.00
Média de gols 8.44
Mediana de gols 7.50
Máximo de gols 22.00
Desvio padrão (gols) 3.26
Média de jogos 13.19
Média de Copas 2.71
Máximo de Copas 6.00

Análise específica do Messi

# Extrair dados do Messi
messi <- artilheiros %>% filter(Jogador == "Lionel Messi")

if (nrow(messi) > 0) {
  # Calcular z-scores
  z_gols <- (messi$Gols - mean(artilheiros$Gols)) / sd(artilheiros$Gols)
  z_jogos <- (messi$Jogos - mean(artilheiros$Jogos)) / sd(artilheiros$Jogos)
  
  dados_messi <- data.frame(
    Métrica = c("Gols", "Jogos", "Média gols/jogo", "Copas", "Z-score gols", "Z-score jogos"),
    Valor = c(messi$Gols, messi$Jogos, messi$Média, messi$n_copas, 
              round(z_gols, 2), round(z_jogos, 2))
  )
  
  kable(dados_messi, caption = "Análise específica: Lionel Messi")
} else {
  warning("Messi não encontrado na base de dados!")
}
Análise específica: Lionel Messi
Métrica Valor
Gols 21.00
Jogos 34.00
Média gols/jogo 0.61
Copas 6.00
Z-score gols 3.85
Z-score jogos 3.39

Matriz de Correlação

# Selecionar variáveis numéricas
variaveis_num <- artilheiros %>%
  select(Gols, Jogos, Média, n_copas, gols_por_copa, jogos_por_copa)

# Calcular matriz de correlação
cor_matrix <- cor(variaveis_num, use = "complete.obs")

# Visualização melhorada
corrplot(
  cor_matrix, 
  method = "color",
  type = "upper",
  tl.col = "black",
  tl.srt = 45,
  addCoef.col = "black",
  number.cex = 0.9,
  title = "Matriz de Correlação entre Variáveis",
  mar = c(0, 0, 2, 0),
  col = colorRampPalette(c("#BB4444", "#EE9988", "#FFFFFF", "#77AADD", "#4477AA"))(200)
)

Ranking ponderado

O ranking combina três métricas normalizadas (z-score) com pesos atribuídos:

  1. Gols totais (peso 0.4) - volume
  2. Média de gols por jogo (peso 0.3) - eficiência
  3. Gols por Copa (peso 0.3) - impacto por edição
# Normalizar variáveis (z-score)
artilheiros <- artilheiros %>%
  mutate(
    z_gols = as.numeric(scale(Gols)),
    z_media = as.numeric(scale(Média)),
    z_gols_copa = as.numeric(scale(gols_por_copa))
  )

# Definir pesos
pesos <- c(gols = 0.4, media = 0.3, gols_copa = 0.3)

# Calcular score ponderado
artilheiros <- artilheiros %>%
  mutate(
    score_ponderado = z_gols * pesos["gols"] + 
                      z_media * pesos["media"] + 
                      z_gols_copa * pesos["gols_copa"]
  )

# Gerar ranking
ranking <- artilheiros %>%
  arrange(desc(score_ponderado)) %>%
  select(Jogador, Seleção, Gols, Média, gols_por_copa, score_ponderado) %>%
  mutate(posicao = row_number())

# Exibir Top 20
kable(
  ranking %>% head(20),
  caption = "Top 20 - Ranking Ponderado",
  digits = 2,
  format = "html",
  booktabs = TRUE
) %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  row_spec(which(ranking$Jogador == "Lionel Messi"), bold = TRUE, background = "#FFE6CC")
Top 20 - Ranking Ponderado
Jogador Seleção Gols Média gols_por_copa score_ponderado posicao
Just Fontaine França 13 2.17 13.00 2.66 1
Kylian Mbappé França 22 1.00 7.33 2.27 2
Sándor Kocsis Hungria 11 2.20 11.00 2.17 3
Lionel Messi Argentina 21 0.61 3.50 1.39 4
Gerd Müller Alemanha Ocidental 14 1.08 7.00 1.30 5
Guillermo Stábile Argentina 8 2.00 8.00 1.28 6
Ademir de Menezes[2] Brasil 9 1.50 9.00 1.22 7
Eusébio Portugal 9 1.50 9.00 1.22 8
Miroslav Klose Alemanha 16 0.67 4.00 0.89 9
Ronaldo Brasil 15 0.79 3.75 0.81 10
Harry Kane Inglaterra 14 0.77 4.67 0.79 11
Josef Hügi Suíça 6 2.00 6.00 0.77 12
Oleg Salenko Rússia 6 2.00 6.00 0.77 13
Erling Haaland Noruega 7 1.40 7.00 0.64 14
Leônidas da Silva[3] Brasil 8 1.60 4.00 0.50 15
Helmut Rahn Alemanha Ocidental 10 1.00 5.00 0.49 16
Pelé Brasil 12 0.86 3.00 0.38 17
Gary Lineker Inglaterra 10 0.83 5.00 0.38 18
Christian Vieri Itália 9 1.00 4.50 0.30 19
Erich Probst Áustria 6 1.20 6.00 0.26 20
# Posição do Messi
pos_messi <- ranking %>% filter(Jogador == "Lionel Messi") %>% pull(posicao)
cat(sprintf("\n📍 Posição de Messi no ranking: %dº de %d jogadores\n", 
            pos_messi, nrow(ranking)))
## 
## 📍 Posição de Messi no ranking: 4º de 72 jogadores

Análise de sensibilidade dos pesos

# Gerar combinações de pesos que somam 1
combinacoes <- expand.grid(
  peso_gols = seq(0.2, 0.6, by = 0.1),
  peso_media = seq(0.1, 0.5, by = 0.1),
  peso_gols_copa = seq(0.1, 0.5, by = 0.1)
) %>%
  filter(abs(peso_gols + peso_media + peso_gols_copa - 1) < 0.001)

# Função para calcular posição do Messi (vetorizada)
calcular_posicao_messi <- function(peso_gols, peso_media, peso_gols_copa) {
  score <- artilheiros$z_gols * peso_gols + 
           artilheiros$z_media * peso_media + 
           artilheiros$z_gols_copa * peso_gols_copa
  
  ranking_temp <- rank(-score)
  idx_messi <- which(artilheiros$Jogador == "Lionel Messi")
  
  return(ranking_temp[idx_messi])
}

# Aplicar função a todas as combinações (vetorizado)
combinacoes <- combinacoes %>%
  mutate(
    posicao_messi = mapply(
      calcular_posicao_messi,
      peso_gols, 
      peso_media, 
      peso_gols_copa
    )
  )

# Identificar melhor e pior cenário
melhor_cenario <- combinacoes %>% filter(posicao_messi == min(posicao_messi)) %>% slice(1)
pior_cenario <- combinacoes %>% filter(posicao_messi == max(posicao_messi)) %>% slice(1)

# Criar dataframe com resultados da análise de sensibilidade
resultados_sensibilidade <- data.frame(
  Cenário = c("Melhor posição", "Pior posição", "Posição média"),
  `Posição de Messi` = c(
    min(combinacoes$posicao_messi),
    max(combinacoes$posicao_messi),
    round(mean(combinacoes$posicao_messi), 1)
  )
)

kable(resultados_sensibilidade, caption = "Análise de sensibilidade dos pesos")
Análise de sensibilidade dos pesos
Cenário Posição.de.Messi
Melhor posição 2.0
Pior posição 14.0
Posição média 6.5
# Exibir melhor combinação
kable(melhor_cenario, caption = "Melhor combinação de pesos para Messi")
Melhor combinação de pesos para Messi
peso_gols peso_media peso_gols_copa posicao_messi
0.6 0.3 0.1 2

Análise de cluster

Metodologia

Utilizamos o método de k-means para agrupar os jogadores por perfil de desempenho, considerando as variáveis normalizadas: Gols, Média, n_copas e gols_por_copa.

Determinação do número ótimo de clusters

# Preparar dados para clustering
dados_cluster <- artilheiros %>%
  select(Gols, Média, n_copas, gols_por_copa) %>%
  scale()

# Método do cotovelo
set.seed(123)
wss <- map_dbl(1:10, ~kmeans(dados_cluster, centers = .x, nstart = 25)$tot.withinss)

# Método do silhouette
silhouette_scores <- map_dbl(2:10, ~{
  km <- kmeans(dados_cluster, centers = .x, nstart = 25)
  sil <- silhouette(km$cluster, dist(dados_cluster))
  mean(sil[, 3])
})

# Gráfico combinado
p_elbow <- ggplot(data.frame(k = 1:10, wss = wss), aes(x = k, y = wss)) +
  geom_line(color = "#4477AA", size = 1.2) +
  geom_point(color = "#CC79A7", size = 3) +
  geom_vline(xintercept = 4, linetype = "dashed", color = "gray50") +
  labs(
    title = "Método do Cotovelo",
    subtitle = "Número ótimo de clusters: k = 4",
    x = "Número de clusters (k)",
    y = "Soma dos quadrados dentro do grupo"
  ) +
  theme_custom()

p_silhouette <- ggplot(data.frame(k = 2:10, sil = silhouette_scores), 
                       aes(x = k, y = sil)) +
  geom_line(color = "#4477AA", size = 1.2) +
  geom_point(color = "#CC79A7", size = 3) +
  geom_vline(xintercept = 4, linetype = "dashed", color = "gray50") +
  labs(
    title = "Método do Silhouette",
    x = "Número de clusters (k)",
    y = "Silhouette Score"
  ) +
  theme_custom()

p_elbow + p_silhouette

Execução do K-Means

# Aplicar k-means com k = 4
set.seed(123)
k <- 4
cluster_result <- kmeans(dados_cluster, centers = k, nstart = 25)

# Adicionar clusters aos dados
artilheiros <- artilheiros %>%
  mutate(cluster = as.factor(cluster_result$cluster))

# Estatísticas por cluster
cluster_stats <- artilheiros %>%
  group_by(cluster) %>%
  summarise(
    n_jogadores = n(),
    media_gols = round(mean(Gols), 1),
    media_eficiencia = round(mean(Média), 2),
    media_copas = round(mean(n_copas), 1),
    media_gols_copa = round(mean(gols_por_copa), 1),
    jogadores_destaque = paste(head(Jogador, 3), collapse = ", "),
    .groups = "drop"
  )

kable(
  cluster_stats,
  caption = "Perfil dos Clusters (k = 4)",
  format = "html",
  booktabs = TRUE
) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Perfil dos Clusters (k = 4)
cluster n_jogadores media_gols media_eficiencia media_copas media_gols_copa jogadores_destaque
1 20 7.2 0.87 1.9 4.1 Helmut Rahn, Gary Lineker, Christian Vieri
2 6 17.0 0.82 3.7 5.0 Kylian Mbappé, Lionel Messi, Miroslav Klose
3 38 7.7 0.52 3.4 2.3 Pelé, Jürgen Klinsmann, Cristiano Ronaldo
4 8 8.6 1.85 1.0 8.6 Just Fontaine, Sándor Kocsis, Ademir de Menezes[2]

Visualização dos clusters

# Análise de Componentes Principais
pca_result <- prcomp(dados_cluster, scale. = TRUE)

# Adicionar componentes principais aos dados
artilheiros <- artilheiros %>%
  mutate(
    PC1 = pca_result$x[, 1],
    PC2 = pca_result$x[, 2]
  )

# Calcular variância explicada
var_explicada <- summary(pca_result)$importance[2, ] * 100

# Gráfico de clusters com PCA
ggplot(artilheiros, aes(x = PC1, y = PC2, color = cluster)) +
  geom_point(aes(size = Gols), alpha = 0.7) +
  geom_text(
    aes(label = ifelse(Gols >= 14 | Jogador %in% c("Lionel Messi", "Kylian Mbappé"), 
                       Jogador, "")),
    vjust = -0.8, size = 3.5, fontface = "bold"
  ) +
  stat_ellipse(aes(group = cluster), level = 0.85, linetype = 2) +
  scale_color_manual(values = paleta_cores) +
  scale_size_continuous(range = c(2, 8)) +
  labs(
    title = "Clusters de artilheiros - visualização **PCA**",
    subtitle = sprintf("PC1 (%.1f%%) vs PC2 (%.1f%%) da variância", 
                       var_explicada[1], var_explicada[2]),
    x = sprintf("Componente Principal 1 (%.1f%%)", var_explicada[1]),
    y = sprintf("Componente Principal 2 (%.1f%%)", var_explicada[2]),
    color = "Cluster",
    size = "Gols"
  ) +
  theme_custom() +
  theme(legend.position = "right")

Interpretação dos clusters

A tabela a seguir apresenta o perfil médio de cada cluster, com os principais jogadores que o compõem. A nomenclatura adotada reflete as características dominantes de cada grupo:

# Caracterização detalhada de cada cluster em tabela formatada

cluster_summary <- artilheiros %>%
  group_by(cluster) %>%
  summarise(
    `Tamanho` = n(),
    `Média de Gols` = round(mean(Gols), 1),
    `Média de Eficiência` = round(mean(Média), 2),
    `Média de Copas` = round(mean(n_copas), 1),
    `Média Gols/Copa` = round(mean(gols_por_copa), 1),
    `Principais Jogadores` = paste(head(Jogador, 3), collapse = ", ")
  )

# Ordenar clusters por média de gols (crescente)
ordem_clusters <- cluster_summary %>%
  arrange(`Média de Gols`) %>%
  pull(cluster)

# Atribuir perfis com base na ordem
cluster_summary <- cluster_summary %>%
  mutate(
    Perfil = case_when(
      cluster == ordem_clusters[1] ~ "Participantes moderados",
      cluster == ordem_clusters[2] ~ "Eficiência sustentada",
      cluster == ordem_clusters[3] ~ "Alta densidade de gols",
      cluster == ordem_clusters[4] ~ "Volume e longevidade"
    )
  )

# Tabela estilizada
cluster_summary %>%
  kable(
    caption = "Perfil dos Clusters de Artilheiros",
    align = c("l", "c", "c", "c", "c", "c", "l"),
    escape = FALSE
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center",
    font_size = 14
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2C3E50") %>%
  column_spec(1, bold = TRUE, color = "#2980B9") %>%
  column_spec(7, width = "25em")
Perfil dos Clusters de Artilheiros
cluster Tamanho Média de Gols Média de Eficiência Média de Copas Média Gols/Copa Principais Jogadores Perfil
1 20 7.2 0.87 1.9 4.1 Helmut Rahn, Gary Lineker, Christian Vieri Participantes moderados
2 6 17.0 0.82 3.7 5.0 Kylian Mbappé, Lionel Messi, Miroslav Klose Volume e longevidade
3 38 7.7 0.52 3.4 2.3 Pelé, Jürgen Klinsmann, Cristiano Ronaldo Eficiência sustentada
4 8 8.6 1.85 1.0 8.6 Just Fontaine, Sándor Kocsis, Ademir de Menezes[2] Alta densidade de gols

Análise de resíduos e regressão

Nesta etapa, geramos gráficos de diagnóstico (resíduos vs. ajustados, Q-Q plot, resíduos padronizados) e testes estatísticos (Shapiro-Wilk para normalidade e Breusch-Pagan para homocedasticidade).

O gráfico de resíduos vs. valores ajustados verifica a homocedasticidade (variância constante) e a linearidade. Pontos sem padrão claro indicam um bom ajuste.

O Q-Q Plot verifica a normalidade dos resíduos. Se os pontos estiverem próximos da linha, os resíduos seguem uma distribuição normal.

Os resíduos padronizados permitem identificar outliers. Valores acima de 2 ou abaixo de -2 merecem atenção.

A distância de Cook mede a influência de cada observação no modelo. Valores maiores que 1 indicam pontos muito influentes.

# Modelo de regressão múltipla
modelo <- lm(Gols ~ Jogos + Média + n_copas + gols_por_copa, data = artilheiros)
cat("\n========== REGRESSÃO MÚLTIPLA ==========\n")
## 
## ========== REGRESSÃO MÚLTIPLA ==========
summary(modelo)
## 
## Call:
## lm(formula = Gols ~ Jogos + Média + n_copas + gols_por_copa, 
##     data = artilheiros)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.5208 -1.2020  0.1679  1.2300  6.2272 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    -4.4028     1.1921  -3.693 0.000447 ***
## Jogos           0.3461     0.1079   3.208 0.002051 ** 
## Média           1.9914     1.3475   1.478 0.144118    
## n_copas         1.1228     0.5710   1.966 0.053404 .  
## gols_por_copa   0.9819     0.2713   3.620 0.000567 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.833 on 67 degrees of freedom
## Multiple R-squared:  0.7023, Adjusted R-squared:  0.6845 
## F-statistic: 39.52 on 4 and 67 DF,  p-value: < 2.2e-16
# O modelo stepwise seleciona automaticamente as variáveis mais relevantes
# com base no critério AIC (Akaike Information Criterion)
modelo_step <- step(modelo, direction = "both", trace = 0)
cat("\n========== MODELO OTIMIZADO (STEPWISE) ==========\n")
## 
## ========== MODELO OTIMIZADO (STEPWISE) ==========
summary(modelo_step)
## 
## Call:
## lm(formula = Gols ~ Jogos + Média + n_copas + gols_por_copa, 
##     data = artilheiros)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.5208 -1.2020  0.1679  1.2300  6.2272 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    -4.4028     1.1921  -3.693 0.000447 ***
## Jogos           0.3461     0.1079   3.208 0.002051 ** 
## Média           1.9914     1.3475   1.478 0.144118    
## n_copas         1.1228     0.5710   1.966 0.053404 .  
## gols_por_copa   0.9819     0.2713   3.620 0.000567 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.833 on 67 degrees of freedom
## Multiple R-squared:  0.7023, Adjusted R-squared:  0.6845 
## F-statistic: 39.52 on 4 and 67 DF,  p-value: < 2.2e-16
# Análise de resíduos
artilheiros$residuos <- residuals(modelo_step)
artilheiros$ajustados <- fitted(modelo_step)
artilheiros$residuos_padronizados <- rstandard(modelo_step)

# Testes de diagnóstico
cat("\n========== TESTES DE DIAGNÓSTICO ==========\n")
## 
## ========== TESTES DE DIAGNÓSTICO ==========
cat("Teste de Shapiro-Wilk (normalidade dos resíduos):\n")
## Teste de Shapiro-Wilk (normalidade dos resíduos):
print(shapiro.test(artilheiros$residuos))
## 
##  Shapiro-Wilk normality test
## 
## data:  artilheiros$residuos
## W = 0.97582, p-value = 0.1798
cat("\nTeste de Breusch-Pagan (homocedasticidade):\n")
## 
## Teste de Breusch-Pagan (homocedasticidade):
print(bptest(modelo_step))
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo_step
## BP = 25.041, df = 4, p-value = 4.937e-05
# Distância de Cook
artilheiros$cook <- cooks.distance(modelo_step)
cat("\n========== DISTÂNCIA DE COOK (OUTLIERS INFLUENTES) ==========\n")
## 
## ========== DISTÂNCIA DE COOK (OUTLIERS INFLUENTES) ==========
influentes <- artilheiros[artilheiros$cook > 4/nrow(artilheiros), ]
if (nrow(influentes) > 0) {
  print(influentes[, c("Jogador", "Gols", "cook")])
} else {
  cat("Nenhum ponto influente detectado.\n")
}
## # A tibble: 8 × 3
##   Jogador            Gols   cook
##   <chr>             <dbl>  <dbl>
## 1 Kylian Mbappé        22 0.454 
## 2 Lionel Messi         21 0.176 
## 3 Just Fontaine        13 0.363 
## 4 Sándor Kocsis        11 0.108 
## 5 Cristiano Ronaldo    11 0.177 
## 6 Josef Hügi            6 0.0749
## 7 Oleg Salenko          6 0.0749
## 8 Lothar Matthäus       6 0.164

Visualizações avançadas

# 1. Gols vs. Jogos com clusters
p1 <- ggplot(artilheiros, aes(x = Jogos, y = Gols, color = cluster)) +
  geom_point(aes(size = n_copas), alpha = 0.7) +
  geom_smooth(method = "lm", se = TRUE, color = "black", linetype = "dashed") +
  geom_text(aes(label = ifelse(Gols >= 12 | Jogador == "Lionel Messi", Jogador, "")), 
            vjust = -0.5, size = 3) +
  labs(title = "Gols vs. Jogos (clusters destacados)",
       x = "Número de jogos",
       y = "Gols totais",
       size = "Número de Copas") +
  theme_minimal() +
  theme(legend.position = "bottom")

# 2. Eficiência vs. longevidade
p2 <- ggplot(artilheiros, aes(x = n_copas, y = Média, color = cluster)) +
  geom_point(aes(size = Gols), alpha = 0.7) +
  geom_text(aes(label = ifelse(Gols >= 12 | Jogador == "Lionel Messi", Jogador, "")), 
            vjust = -0.5, size = 3) +
  labs(title = "Eficiência vs. longevidade",
       x = "Número de Copas disputadas",
       y = "Média de gols por jogo",
       size = "Gols totais") +
  theme_minimal() +
  theme(legend.position = "bottom")

# 3. Resíduos padronizados
p3 <- ggplot(artilheiros, aes(x = reorder(Jogador, residuos_padronizados), 
                              y = residuos_padronizados, 
                              fill = residuos_padronizados > 0)) +
  geom_col() +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_hline(yintercept = c(-2, 2), linetype = "dotted", color = "red") +
  coord_flip() +
  labs(title = "Resíduos padronizados por jogador",
       x = "Jogador",
       y = "Resíduo padronizado") +
  theme_minimal() +
  theme(legend.position = "none")

print(p1)

print(p2)

print(p3)

Interpretação dos resultados

Ranking ponderado

  1. Just Fontaine e Sándor Kocsis lideram o ranking devido à altíssima eficiência (2,17 e 2,20 gols/jogo) em apenas uma Copa.
  2. Messi aparece em posição modesta (em 4º lugar) porque, embora tenha o segundo maior volume de gols, sua eficiência é inferior.
  3. A análise de sensibilidade mostra que a posição de Messi varia entre 2º e 14º dependendo dos pesos atribuídos.

Clusters identificados

  • Cluster 1 (Participantes moderados): Jogadores com desempenho médio em todas as métricas, representando a maioria dos artilheiros (Helmut Rahn, Gary Lineker, Christian Vieri).

  • Cluster 2 (Volume e longevidade): Jogadores com o maior número de gols (média 14.7) e o maior número de Copas (média 3.9), indicando que o volume de gols está associado à longevidade no torneio (Lionel Messi, Kylian Mbappé, Miroslav Klose).

  • Cluster 3 (Eficiência sustentada): Jogadores com boa eficiência (média 0.48) em poucas Copas (média 2.0), indicando desempenho consistente em participações limitadas (Pelé, Jürgen Klinsmann, Cristiano Ronaldo).

  • Cluster 4 (Alta densidade de gols): Jogadores com eficiência excepcional (média 1.89) em uma única Copa (média 1.0), caracterizando performances históricas concentradas (Just Fontaine, Sándor Kocsis, Ademir de Menezes).

Messi pertence ao Cluster 2, caracterizado por longevidade e volume, ou seja, seu recorde é explicado pelo acúmulo de gols ao longo de múltiplas edições, não por eficiência excepcional por jogo ou por Copa.

Considerações finais

Com base em cinco camadas analíticas:

Critério Conclusão
Gols totais Messi, com 21 gols, foi superado por Mbappé (22)
Eficiência (gols/jogo) Messi está entre os piores (0,61)
Gols por Copa Messi tem média 3,50, inferior a muitos
Ranking ponderado Messi fica entre 2º e 14º
Cluster Pertence ao grupo de volume e longevidade

Concluímos que:

Messi é o segundo maior artilheiro em números absolutos, mas isso se deve mais à sua extraordinária longevidade (6 Copas) do que à sua eficiência por jogo ou por Copa. Em termos de impacto por edição, jogadores como Just Fontaine, Sándor Kocsis e Kylian Mbappé foram estatisticamente superiores.

A contagem absoluta favorece quem joga mais. A média favorece quem joga menos e faz mais gols. Não há resposta única — depende do que se quer medir.

Limitações

  • Efeito de período: diferentes épocas do futebol têm contextos táticos e número de jogos por Copa distintos;
  • Padronização de dados: a média de gols por jogo foi calculada com base nos dados disponíveis, mas pode haver variações na contagem oficial de jogos;
  • Interpretação dos clusters: a análise de agrupamento é exploratória e os resultados devem ser interpretados com cautela.

Apesar dessas limitações, a análise combinada oferece insights valiosos sobre o perfil dos artilheiros históricos da Copa do Mundo.

Referências

  • Beggs, Clive (2024). Soccer Analytics: An Introduction Using R. CRC Press, Taylor & Francis Group.

  • Bradley Boehmke (2018). Scraping Data: UC Business Analytics R Programming Guide. https://uc-r.github.io/scraping.

  • Kabacoff, Robert I. (2011). R in Action - Data analysis and graphics with R. Manning Publications Co.

  • Kerns, G. J. (2010). Introduction to probability and statistics using R (First edition). Disponível em: https://www.atmos.albany.edu/facstaff/timm/ATM315spring14/R/IPSUR.pdf.

  • Zumel, N., & Mount, J. (2014). Practical Data Science with R. Manning Publications.