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:
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 |
|---|---|---|---|---|---|
| Lionel Messi | Argentina | 19 | 29 | 0.65 | 6 |
| Kylian Mbappé | França | 18 | 18 | 1.00 | 3 |
| 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 |
| 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 |
| Harry Kane | Inglaterra | 11 | 14 | 0.78 | 3 |
| 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 | 105.00 |
| Média de gols | 7.16 |
| Mediana de gols | 6.00 |
| Máximo de gols | 19.00 |
| Desvio padrão (gols) | 2.86 |
| Média de jogos | 11.75 |
| Média de Copas | 2.63 |
| 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 | 19.00 |
| Jogos | 29.00 |
| Média gols/jogo | 0.65 |
| Copas | 6.00 |
| Z-score gols | 4.14 |
| Z-score jogos | 3.17 |
# 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 | 3.25 | 1 |
| Sándor Kocsis | Hungria | 11 | 2.20 | 11.00 | 2.70 | 2 |
| Kylian Mbappé | França | 18 | 1.00 | 6.00 | 2.10 | 3 |
| Gerd Müller | Alemanha Ocidental | 14 | 1.08 | 7.00 | 1.74 | 4 |
| Guillermo Stábile | Argentina | 8 | 2.00 | 8.00 | 1.70 | 5 |
| Ademir de Menezes[2] | Brasil | 9 | 1.50 | 9.00 | 1.63 | 6 |
| Eusébio | Portugal | 9 | 1.50 | 9.00 | 1.63 | 7 |
| Lionel Messi | Argentina | 19 | 0.65 | 3.17 | 1.58 | 8 |
| Miroslav Klose | Alemanha | 16 | 0.67 | 4.00 | 1.30 | 9 |
| Ronaldo | Brasil | 15 | 0.79 | 3.75 | 1.21 | 10 |
| Josef Hügi | Suíça | 6 | 2.00 | 6.00 | 1.13 | 11 |
| Oleg Salenko | Rússia | 6 | 2.00 | 6.00 | 1.13 | 12 |
| Helmut Rahn | Alemanha Ocidental | 10 | 1.00 | 5.00 | 0.84 | 13 |
| Leônidas da Silva[3] | Brasil | 8 | 1.60 | 4.00 | 0.84 | 14 |
| Pelé | Brasil | 12 | 0.86 | 3.00 | 0.73 | 15 |
| Gary Lineker | Inglaterra | 10 | 0.83 | 5.00 | 0.72 | 16 |
| Harry Kane | Inglaterra | 11 | 0.78 | 3.67 | 0.63 | 17 |
| Christian Vieri | Itália | 9 | 1.00 | 4.50 | 0.62 | 18 |
| Max Morlock | Alemanha Ocidental | 6 | 1.20 | 6.00 | 0.56 | 19 |
| Erich Probst | Áustria | 6 | 1.20 | 6.00 | 0.56 | 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: 8º de 105 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 | 3.0 |
| Pior posição | 15.0 |
| Posição média | 7.4 |
| peso_gols | peso_media | peso_gols_copa | posicao_messi |
|---|---|---|---|
| 0.6 | 0.3 | 0.1 | 3 |
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 | 50 | 6.5 | 0.46 | 3.4 | 2.0 | Thomas Müller, Cristiano Ronaldo, Grzegorz Lato |
| 2 | 10 | 13.6 | 0.81 | 3.5 | 4.1 | Lionel Messi, Kylian Mbappé, Miroslav Klose |
| 3 | 7 | 8.9 | 1.91 | 1.0 | 8.9 | Just Fontaine, Sándor Kocsis, Ademir de Menezes[2] |
| 4 | 38 | 6.1 | 0.86 | 1.7 | 3.7 | Helmut Rahn, Gary Lineker, Christian Vieri |
# 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
# 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 = ", ")
) %>%
mutate(
cluster = paste("Cluster", cluster),
Perfil = case_when(
# Cluster 1: Média de Copas = 3.3, Média Eficiência = 0.46 → Participantes moderados
cluster == "Cluster 1" ~ "Participantes moderados",
# Cluster 2: Média de Copas = 1.8, Média Eficiência = 0.85 → Eficiência sustentada
cluster == "Cluster 2" ~ "Eficiência sustentada",
# Cluster 3: Média de Copas = 1.0, Média Eficiência = 1.91 → Alta densidade de gols
cluster == "Cluster 3" ~ "Alta densidade de gols",
# Cluster 4: Média de Copas = 3.7, Média Gols = 12.6 → Volume e longevidade
cluster == "Cluster 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 |
|---|---|---|---|---|---|---|---|
| Cluster 1 | 50 | 6.5 | 0.46 | 3.4 | 2.0 | Thomas Müller, Cristiano Ronaldo, Grzegorz Lato | Participantes moderados |
| Cluster 2 | 10 | 13.6 | 0.81 | 3.5 | 4.1 | Lionel Messi, Kylian Mbappé, Miroslav Klose | Eficiência sustentada |
| Cluster 3 | 7 | 8.9 | 1.91 | 1.0 | 8.9 | Just Fontaine, Sándor Kocsis, Ademir de Menezes[2] | Alta densidade de gols |
| Cluster 4 | 38 | 6.1 | 0.86 | 1.7 | 3.7 | Helmut Rahn, Gary Lineker, Christian Vieri | Volume e longevidade |
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
## -4.9526 -0.9241 0.1497 0.7720 5.3975
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.14955 0.80862 -5.132 1.41e-06 ***
## Jogos 0.32421 0.07109 4.560 1.45e-05 ***
## Média 2.57965 1.02294 2.522 0.0133 *
## n_copas 1.07055 0.34798 3.076 0.0027 **
## gols_por_copa 0.85416 0.20741 4.118 7.87e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.541 on 100 degrees of freedom
## Multiple R-squared: 0.7207, Adjusted R-squared: 0.7095
## F-statistic: 64.5 on 4 and 100 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
## -4.9526 -0.9241 0.1497 0.7720 5.3975
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.14955 0.80862 -5.132 1.41e-06 ***
## Jogos 0.32421 0.07109 4.560 1.45e-05 ***
## Média 2.57965 1.02294 2.522 0.0133 *
## n_copas 1.07055 0.34798 3.076 0.0027 **
## gols_por_copa 0.85416 0.20741 4.118 7.87e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.541 on 100 degrees of freedom
## Multiple R-squared: 0.7207, Adjusted R-squared: 0.7095
## F-statistic: 64.5 on 4 and 100 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.97796, p-value = 0.07739
##
## Teste de Breusch-Pagan (homocedasticidade):
##
## studentized Breusch-Pagan test
##
## data: modelo_step
## BP = 44.528, df = 4, p-value = 4.984e-09
# 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: 12 × 3
## Jogador Gols cook
## <chr> <dbl> <dbl>
## 1 Lionel Messi 19 0.212
## 2 Kylian Mbappé 18 0.174
## 3 Miroslav Klose 16 0.0826
## 4 Ronaldo 15 0.0535
## 5 Gerd Müller 14 0.0570
## 6 Just Fontaine 13 0.367
## 7 Sándor Kocsis 11 0.138
## 8 Cristiano Ronaldo 10 0.122
## 9 Guillermo Stábile 8 0.0569
## 10 Josef Hügi 6 0.135
## 11 Oleg Salenko 6 0.135
## 12 Lothar Matthäus 6 0.181
# 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 (David Villa, Paolo Rossi, Jairzinho).
Cluster 2 (Eficiência sustentada): Jogadores com boa eficiência (média 0.85) em poucas Copas (média 1.8), indicando desempenho consistente em participações limitadas (Helmut Rahn, Gary Lineker, Christian Vieri).
Cluster 3 (Alta densidade de gols): Jogadores com eficiência excepcional (média 1.91) em uma única Copa (média 1.0), caracterizando performances históricas concentradas (Just Fontaine, Sándor Kocsis, Ademir de Menezes).
Cluster 4 (Volume e longevidade): Jogadores com o maior número de gols (média 12.6) e o maior número de Copas (média 3.7), indicando que o volume de gols está associado à longevidade no torneio (Lionel Messi, Kylian Mbappé, Miroslav Klose).
Messi pertence ao Cluster 4, 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 é o maior (19 gols) |
| Eficiência (gols/jogo) | Messi está entre os piores (0,65) |
| Gols por Copa | Messi tem média 3,17, inferior a muitos |
| Ranking ponderado | Messi fica entre 2º e 15º |
| Cluster | Pertence ao grupo de volume e longevidade |
Concluímos que:
Messi é o 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.