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 |
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:
P.S.: considerando o desfecho do torneio, a pergunta perdeu a relevância.
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")# 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"))| 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 |
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.
Este estudo adota cinco abordagens complementares:
A combinação dessas perspectivas permite uma avaliação mais adequada do desempenho dos artilheiros.
# 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")| 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 |
# 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!")
}| 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 |
# 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)
)O ranking combina três métricas normalizadas (z-score) com pesos atribuídos:
# 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")| 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
# 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")| Cenário | Posição.de.Messi |
|---|---|
| Melhor posição | 2.0 |
| Pior posição | 14.0 |
| Posição média | 6.5 |
| peso_gols | peso_media | peso_gols_copa | posicao_messi |
|---|---|---|---|
| 0.6 | 0.3 | 0.1 | 2 |
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.
# 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# 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"))| 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] |
# 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")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")| 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 |
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 ==========
##
## 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) ==========
##
## 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 ==========
## Teste de Shapiro-Wilk (normalidade dos resíduos):
##
## Shapiro-Wilk normality test
##
## data: artilheiros$residuos
## W = 0.97582, p-value = 0.1798
##
## Teste de Breusch-Pagan (homocedasticidade):
##
## 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
# 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)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.
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.
Apesar dessas limitações, a análise combinada oferece insights valiosos sobre o perfil dos artilheiros históricos da Copa do Mundo.
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.