O desempenho escolar é influenciado por múltiplos fatores, entre eles o histórico de notas, a frequência, os hábitos de estudo e o contexto familiar e social. A análise exploratória de dados permite resumir essas informações, identificar padrões e formular hipóteses que podem orientar investigações educacionais. Entretanto, associações estatísticas não demonstram, por si só, relações de causa e efeito.
Este relatório utiliza dados públicos de estudantes do ensino
secundário de duas escolas, disponibilizados no repositório UCI Machine
Learning Repository. O conjunto contém informações demográficas,
escolares e sociais, além de notas de períodos letivos. A análise abaixo
utiliza o arquivo de Matemática (student-mat.csv) e
considera a nota final G3 como variável de interesse.
O código utiliza dplyr e ggplot2 para
manipulação e visualização, DT para a tabela interativa e
knitr para apresentar tabelas resumidas. Caso ainda não
estejam instalados, execute uma vez no console do R:
install.packages(c("dplyr", "ggplot2", "DT", "knitr", "rmarkdown"))
library(dplyr)
library(ggplot2)
library(DT)
library(knitr)
O arquivo original está disponível no UCI Machine Learning Repository. O código baixa o arquivo ZIP, extrai os arquivos CSV e lê a base de Matemática. Os dados originais usam ponto e vírgula como separador.
# Lê o arquivo diretamente da pasta do projeto
# O arquivo deve ser baixado na url: https://archive.ics.uci.edu/static/public/320/student+performance.zip
dados_originais <- read.csv(
"student-mat.csv",
sep = ";",
stringsAsFactors = FALSE
)
# Confere se os dados foram carregados
dim(dados_originais)
## [1] 395 33
head(dados_originais)
A função dim() informa o número de linhas e colunas;
names() lista as variáveis; e head() mostra as
primeiras observações. A base de Matemática contém registros individuais
de estudantes e variáveis como idade, faltas e notas dos três períodos.
A nota G3 varia de 0 a 20.
str(dados_originais)
## 'data.frame': 395 obs. of 33 variables:
## $ school : chr "GP" "GP" "GP" "GP" ...
## $ sex : chr "F" "F" "F" "F" ...
## $ age : int 18 17 15 15 16 16 16 17 15 15 ...
## $ address : chr "U" "U" "U" "U" ...
## $ famsize : chr "GT3" "GT3" "LE3" "GT3" ...
## $ Pstatus : chr "A" "T" "T" "T" ...
## $ Medu : int 4 1 1 4 3 4 2 4 3 3 ...
## $ Fedu : int 4 1 1 2 3 3 2 4 2 4 ...
## $ Mjob : chr "at_home" "at_home" "at_home" "health" ...
## $ Fjob : chr "teacher" "other" "other" "services" ...
## $ reason : chr "course" "course" "other" "home" ...
## $ guardian : chr "mother" "father" "mother" "mother" ...
## $ traveltime: int 2 1 1 1 1 1 1 2 1 1 ...
## $ studytime : int 2 2 2 3 2 2 2 2 2 2 ...
## $ failures : int 0 0 3 0 0 0 0 0 0 0 ...
## $ schoolsup : chr "yes" "no" "yes" "no" ...
## $ famsup : chr "no" "yes" "no" "yes" ...
## $ paid : chr "no" "no" "yes" "yes" ...
## $ activities: chr "no" "no" "no" "yes" ...
## $ nursery : chr "yes" "no" "yes" "yes" ...
## $ higher : chr "yes" "yes" "yes" "yes" ...
## $ internet : chr "no" "yes" "yes" "yes" ...
## $ romantic : chr "no" "no" "no" "yes" ...
## $ famrel : int 4 5 4 3 4 5 4 4 4 5 ...
## $ freetime : int 3 3 3 2 3 4 4 1 2 5 ...
## $ goout : int 4 3 2 2 2 2 4 4 2 1 ...
## $ Dalc : int 1 1 2 1 1 1 1 1 1 1 ...
## $ Walc : int 1 1 3 1 2 2 1 1 1 1 ...
## $ health : int 3 3 3 5 5 5 3 1 1 5 ...
## $ absences : int 6 4 10 2 4 10 0 6 0 0 ...
## $ G1 : int 5 5 7 15 6 15 12 6 16 14 ...
## $ G2 : int 6 5 8 14 10 15 12 5 18 15 ...
## $ G3 : int 6 6 10 15 10 15 11 6 19 15 ...
# Contagem de valores ausentes por coluna
ausentes <- colSums(is.na(dados_originais))
data.frame(
variavel = names(ausentes),
valores_ausentes = as.integer(ausentes)
) |>
arrange(desc(valores_ausentes)) |>
head(10)
# Resumo estatístico das variáveis numéricas
summary(dados_originais[, c("age", "absences", "G1", "G2", "G3")])
## age absences G1 G2
## Min. :15.0 Min. : 0.000 Min. : 3.00 Min. : 0.00
## 1st Qu.:16.0 1st Qu.: 0.000 1st Qu.: 8.00 1st Qu.: 9.00
## Median :17.0 Median : 4.000 Median :11.00 Median :11.00
## Mean :16.7 Mean : 5.709 Mean :10.91 Mean :10.71
## 3rd Qu.:18.0 3rd Qu.: 8.000 3rd Qu.:13.00 3rd Qu.:13.00
## Max. :22.0 Max. :75.000 Max. :19.00 Max. :19.00
## G3
## Min. : 0.00
## 1st Qu.: 8.00
## Median :11.00
## Mean :10.42
## 3rd Qu.:14.00
## Max. :20.00
A inspeção permite verificar tipos de dados, possíveis valores
ausentes e a distribuição inicial das variáveis. A ausência de valores
NA não garante que todos os dados sejam perfeitos: valores
extremos ou registros inconsistentes também devem ser considerados à luz
do contexto.
dados <- dados_originais |>
# Mantém as variáveis mais relevantes para a análise
select(school, sex, age, address, studytime, failures,
absences, G1, G2, G3) |>
# Exclui registros sem informação nas variáveis principais
filter(!is.na(G1), !is.na(G2), !is.na(G3)) |>
# Cria variáveis derivadas para facilitar a interpretação
mutate(
media_parcial = (G1 + G2) / 2,
variacao_final = G3 - media_parcial,
faixa_nota = case_when(
G3 < 10 ~ "Abaixo de 10",
G3 >= 10 ~ "10 ou mais"
),
faixa_nota = factor(faixa_nota,
levels = c("Abaixo de 10", "10 ou mais")),
sexo = recode(sex, F = "Feminino", M = "Masculino"),
escola = recode(school, GP = "Gabriel Pereira",
MS = "Mousinho da Silveira")
) |>
# Ordena da maior para a menor nota final
arrange(desc(G3), desc(G2))
# Conferir os primeiros registros já tratados
head(dados, 10)
Neste processamento:
select() mantém apenas as colunas relevantes.filter() retira linhas sem notas essenciais.mutate() cria a média das notas dos dois primeiros
períodos (media_parcial), a diferença entre a nota final e
essa média (variacao_final) e uma categoria descritiva de
nota.recode() substitui códigos abreviados por rótulos mais
legíveis.arrange() ordena os registros pela nota final, da maior
para a menor.A categoria “10 ou mais” é apenas um agrupamento descritivo usado neste relatório; não deve ser interpretada como uma classificação universal de aprovação, pois regras institucionais podem variar.
indicadores <- dados |>
summarise(
numero_estudantes = n(),
idade_media = mean(age, na.rm = TRUE),
faltas_medias = mean(absences, na.rm = TRUE),
nota_final_media = mean(G3, na.rm = TRUE),
nota_final_mediana = median(G3, na.rm = TRUE),
desvio_padrao_G3 = sd(G3, na.rm = TRUE),
percentual_nota_10_ou_mais = mean(G3 >= 10, na.rm = TRUE) * 100
)
knitr::kable(
indicadores,
digits = 2,
caption = "Resumo descritivo dos estudantes incluídos na análise"
)
| numero_estudantes | idade_media | faltas_medias | nota_final_media | nota_final_mediana | desvio_padrao_G3 | percentual_nota_10_ou_mais |
|---|---|---|---|---|---|---|
| 395 | 16.7 | 5.71 | 10.42 | 11 | 4.58 | 67.09 |
A média resume o desempenho médio, enquanto a mediana representa o ponto central da distribuição. O desvio-padrão descreve a dispersão das notas em torno da média. O percentual de notas iguais ou superiores a 10 é apresentado como uma referência descritiva, não como conclusão sobre aprovação formal.
O pacote DT integra tabelas do R à biblioteca JavaScript
DataTables, oferecendo pesquisa, ordenação e paginação em documentos
HTML (Xie et al., 2025). A tabela abaixo exibe uma seleção de variáveis
e permite explorar os registros.
tabela_estudantes <- dados |>
select(escola, sexo, age, studytime, failures,
absences, G1, G2, G3, media_parcial, variacao_final)
DT::datatable(
tabela_estudantes,
rownames = FALSE,
filter = "top",
extensions = "Buttons",
options = list(
pageLength = 10,
lengthMenu = c(5, 10, 20, 50),
searching = TRUE,
ordering = TRUE,
paging = TRUE,
scrollX = TRUE,
dom = "Blfrtip",
buttons = c("copy", "csv")
),
caption = "Tabela 1. Registros de estudantes e variáveis de desempenho"
)
Como explorar a tabela: digite termos nos campos de filtro para restringir os registros; clique nos títulos das colunas para ordenar; e use os controles de paginação para navegar. Os botões de exportação podem depender do suporte do navegador e da versão instalada do pacote. Para que o widget interativo funcione, renderize o arquivo como HTML.
As equações seguintes ilustram medidas úteis para resumir e estudar o desempenho. Elas são apresentadas como ferramentas metodológicas; os valores específicos devem ser obtidos executando os trechos de código associados.
\[ \bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_i \]
A média amostral é a soma dos valores observados dividida pelo número
de observações. Neste estudo, \(x_i\)
pode representar a nota final G3 do estudante \(i\), e \(n\) é o total de estudantes analisados. A
média é sensível a valores extremos.
mean(dados$G3, na.rm = TRUE)
## [1] 10.41519
\[ s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2 \]
A variância mede a dispersão dos valores em torno da média, usando \(n-1\) no denominador para estimar a variância populacional a partir de uma amostra. Sua unidade é o quadrado da unidade original; por isso, o desvio-padrão costuma ser mais fácil de interpretar diretamente.
var(dados$G3, na.rm = TRUE)
## [1] 20.98962
\[ r_{XY} = \frac{\sum_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y})} {\sqrt{\sum_{i=1}^{n}(x_i-\bar{x})^2} \sqrt{\sum_{i=1}^{n}(y_i-\bar{y})^2}} \]
O coeficiente de Pearson mede a intensidade e a direção da associação linear entre duas variáveis quantitativas. Seu valor varia de \(-1\) a \(1\): valores positivos indicam associação linear positiva, valores negativos indicam associação negativa e valores próximos de zero indicam pouca associação linear. Correlação não implica causalidade.
cor(dados$G2, dados$G3, use = "complete.obs", method = "pearson")
## [1] 0.904868
\[ Y_i = \beta_0 + \beta_1 X_i + \varepsilon_i \]
Nesta expressão, \(Y_i\) é a nota
final G3, \(X_i\) pode ser
a nota do segundo período G2, \(\beta_0\) é o intercepto, \(\beta_1\) representa a variação média
esperada em G3 associada a uma unidade adicional em
G2, e \(\varepsilon_i\)
representa fatores não explicados pelo modelo. A interpretação de \(\beta_1\) é associativa, não
necessariamente causal.
modelo_linear <- lm(G3 ~ G2, data = dados)
summary(modelo_linear)
##
## Call:
## lm(formula = G3 ~ G2, data = dados)
##
## Residuals:
## Min 1Q Median 3Q Max
## -9.6284 -0.3326 0.2695 1.0653 3.5759
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.39276 0.29694 -4.69 3.77e-06 ***
## G2 1.10211 0.02615 42.14 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.953 on 393 degrees of freedom
## Multiple R-squared: 0.8188, Adjusted R-squared: 0.8183
## F-statistic: 1776 on 1 and 393 DF, p-value: < 2.2e-16
\[ (\hat{\beta}_0,\hat{\beta}_1) = \underset{\beta_0,\beta_1}{\operatorname{arg\,min}} \sum_{i=1}^{n} \left[Y_i-(\beta_0+\beta_1X_i)\right]^2 \]
O método dos mínimos quadrados ordinários escolhe os coeficientes que minimizam a soma dos quadrados dos resíduos, isto é, das diferenças entre notas observadas e notas estimadas. O resumo do modelo apresenta coeficientes, erros-padrão e medidas de ajuste. A validade das inferências depende de pressupostos como forma funcional adequada, independência dos erros e comportamento dos resíduos.
coef(modelo_linear)
## (Intercept) G2
## -1.392758 1.102112
ggplot(dados, aes(x = G3)) +
geom_histogram(binwidth = 1, boundary = -0.5,
color = "white", fill = "steelblue") +
geom_vline(xintercept = mean(dados$G3, na.rm = TRUE),
linetype = "dashed", linewidth = 0.8) +
labs(
title = "Distribuição das notas finais",
subtitle = "A linha tracejada indica a média da amostra",
x = "Nota final (G3), de 0 a 20",
y = "Número de estudantes"
) +
theme_minimal(base_size = 12)
Figura 1. Distribuição das notas finais (G3) dos estudantes de Matemática.
O histograma mostra a frequência de estudantes em cada intervalo de nota e ajuda a identificar concentração, assimetria e valores pouco frequentes. A linha tracejada marca a média. A forma concreta da distribuição deve ser descrita a partir do gráfico produzido ao executar o relatório, sem presumir antecipadamente que as notas sejam simétricas ou concentradas em determinada faixa.
ggplot(dados, aes(x = G2, y = G3)) +
geom_point(alpha = 0.55, position = position_jitter(width = 0.08, height = 0.08)) +
geom_smooth(method = "lm", formula = y ~ x,
se = TRUE, color = "firebrick") +
labs(
title = "Nota do segundo período e nota final",
subtitle = "Linha de regressão linear com intervalo de confiança",
x = "Nota do segundo período (G2)",
y = "Nota final (G3)"
) +
theme_minimal(base_size = 12)
Figura 2. Relação entre as notas G2 e G3; a linha representa o ajuste linear simples.
O gráfico de dispersão permite avaliar se notas mais altas em
G2 tendem a acompanhar notas mais altas em G3,
além de revelar dispersão e observações atípicas. A linha representa a
tendência linear estimada e a faixa sombreada, seu intervalo de
confiança. Como as notas são de períodos do mesmo ano letivo, existe uma
relação temporal e conceitual entre elas; portanto, G2 não
deve ser interpretada como causa isolada do desempenho final.
Os resultados numéricos gerados nas seções anteriores permitem
descrever o conjunto analisado em termos de tamanho, idade, frequência e
desempenho. A tabela interativa possibilita localizar observações
individuais; o histograma resume a distribuição de G3; e o
gráfico de dispersão compara G2 com G3.
A associação entre notas parciais e nota final deve ser interpretada com cautela. A própria definição das notas envolve etapas do mesmo processo letivo, de modo que uma associação elevada pode refletir continuidade no desempenho e a forma como as notas são construídas. Outras variáveis disponíveis — como faltas, tempo de estudo e reprovações anteriores — poderiam ser exploradas em análises adicionais.
G3 é limitada ao intervalo de 0 a 20 e pode
não seguir os pressupostos de modelos lineares em todos os
contextos.Este relatório demonstra um fluxo reproduzível de análise exploratória em R: carregamento de dados públicos, inspeção, seleção, filtragem, ordenação, criação de variáveis, resumo estatístico, tabela interativa, equações em LaTeX e visualizações. A análise ajuda a organizar evidências sobre o desempenho escolar, mas não substitui conhecimento pedagógico nem uma investigação desenhada para avaliar causas. Para aprofundar o estudo, recomenda-se examinar simultaneamente frequência, tempo de estudo e histórico escolar, verificar os pressupostos dos modelos e validar conclusões em outros conjuntos de dados.
Cortez, P. (2008). Student Performance [Conjunto de dados]. UCI Machine Learning Repository. https://doi.org/10.24432/C5TG7T
Cortez, P., & Silva, A. M. G. (2008). Using data mining to predict secondary school student performance. In Proceedings of the 5th Annual Future Business Technology Conference.
Wickham, H., & Grolemund, G. (2017). R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. O’Reilly Media. https://r4ds.hadley.nz/
Xie, Y., Allaire, J. J., & Grolemund, G. (2018). R Markdown: The Definitive Guide. Chapman and Hall/CRC. https://bookdown.org/yihui/rmarkdown/
Xie, Y., Cheng, J., & Tan, X. (2025). DT: A Wrapper of the JavaScript Library ‘DataTables’ (R package, versão 0.34.0). Comprehensive R Archive Network. https://CRAN.R-project.org/package=DT