Previsão de Matrículas UFPE em 2026
Metodologia
Este relatório apresenta a modelagem e previsão do número de matrículas na UFPE para os seguintes níveis:
- Graduação presencial,
- Graduação EAD,
- Mestrado
- Doutorado
Foram utilizadas abordagens como ARIMA com drift e regressão linear para séries temporais anuais (ou semestrais, no caso da graduação), com base em dados de 2016 a 2024.
Graduação Presencial
Para a graduação presencial, utilizamos os dados do Censo da Educação Superior entre 2016 e 2024. Para o ano de 2025, incluímos dados do SIGAA. Como os dados são semestrais, temos 19 observações.
Primeiramente vamos plotar o gráfico da série:
# Previsoes de quantitativos de alunos UFPE 2026 graduacao presencial
library(readxl)
library(forecast)
library(tseries)
library(dplyr)
library(magrittr)
library(reactable)
# Graduação ---------------------------------------------------------------
# abrindo os dados
graduacao_discentes <- read_excel("dados/graduacao_discentes_COD.xlsx",
sheet = "graduacao_matriculados")
# graduacao presencial:
graduacao_presencial_2025 = tibble(ANO="2025", PERIODO_REFERENCIA = "1",
Matriculados = 28972)
graduacao_discentes %>% select(ANO:Matriculados) %>%
filter(MODALIDADE_ENSINO == "Presencial") %>%
group_by(ANO, PERIODO_REFERENCIA) %>%
summarise(Matriculados = sum(Matriculados)) %>%
bind_rows(graduacao_presencial_2025) %>% ungroup %>%
select(Matriculados) -> graduacao_presencial
graduacao_presencial %<>% ts(start =2016, frequency = 2)
# plot
autoplot(graduacao_presencial)
Pelo gráfico da função de autocorrelação, vemos que a série não é estacionária. São necessárias duas diferenciações para que a série se torne estacionária:
Agora, vamos utilizar a função auto.arima para modelar os dados e obter a previsão para os dois semestres de 2026. Para obter a previsão do ano de 2026, vamos computar a média dos valores previstos para 2026.1 e 2026.2.
modelo_graduacao_presencial <- auto.arima(graduacao_presencial,
stepwise = FALSE,
approximation = FALSE)
summary(modelo_graduacao_presencial)
## Series: graduacao_presencial
## ARIMA(0,0,1)(0,1,0)[2]
##
## Coefficients:
## ma1
## 0.7817
## s.e. 0.2227
##
## sigma^2 = 296572: log likelihood = -131.18
## AIC=266.35 AICc=267.21 BIC=268.02
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set -115.7306 499.7451 335.3272 -0.4085656 1.17082 0.6728708
## ACF1
## Training set -0.1321211
# checando os residuos do modelo:
# Conclusão: os resíduos não têm autocorrelação significativa
checkresiduals(modelo_graduacao_presencial)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,1)(0,1,0)[2]
## Q* = 0.72252, df = 3, p-value = 0.8679
##
## Model df: 1. Total lags used: 4
# Previsoes
previsao <- forecast(modelo_graduacao_presencial, h = 6)
#autoplot(previsao)
# Valores previstos para 2026.1 e 2026.2 (segundo e terceiro período futuro)
valores_2026 <- previsao$mean[2:3]
Assim, obtemos o valor previsto para as matrícula da graduação presencial em 2026:
## [1] 28654
Graduação EaD
Seguindo a mesma metodologia, obtemos a previsão para o ano de 2026 para a graduação a distância.
Observação: no caso da graduação EAD, não incluímos os dados de 2025, pois o número era muito divergente em relação ao histórico.
# Previsoes de quantitativos de alunos UFPE 2026 graduacao EAD
library(readxl)
library(forecast)
library(tseries)
library(dplyr)
library(magrittr)
library(ggplot2)
setwd("G:/Meu Drive/workspace/previsao_PLOA/")
# Graduação ---------------------------------------------------------------
# abrindo os dados
graduacao_discentes <- read_excel("dados/graduacao_discentes_COD.xlsx",
sheet = "graduacao_matriculados")
# graduacao EAD:
graduacao_discentes %>% select(ANO:Matriculados) %>%
filter(MODALIDADE_ENSINO == "EaD") %>%
group_by(ANO, PERIODO_REFERENCIA) %>%
summarise(Matriculados = sum(Matriculados)) %>%
# bind_rows(graduacao_EAD_2025) %>%
ungroup %>%
select(Matriculados) -> graduacao_EAD
graduacao_EAD %<>% ts(start =2016, frequency = 2)
# visualizacao
# autoplot(graduacao_EAD) +
# ggtitle("Matrículas em cursos EAD - UFPE") +
# xlab("Ano") + ylab("Número de Matriculados")
#
# # analise de estacionariedade
# autoplot(diff(graduacao_EAD))
# ggAcf(diff(graduacao_EAD))
#
# # Teste de Dickey-Fuller aumentado (ADF)
# # a serie nao eh estacionaria, vamos tentar uma diferenciacao
# adf.test(graduacao_EAD)
#
# graduacao_EAD_diff1 <- diff(graduacao_EAD)
# autoplot(graduacao_EAD_diff1)
# ggAcf(graduacao_EAD_diff1)
# adf.test(graduacao_EAD_diff1)
# Modelagem ARIMA
modelo_ead <- auto.arima(graduacao_EAD, stepwise = FALSE, approximation = FALSE)
summary(modelo_ead)
## Series: graduacao_EAD
## ARIMA(0,0,0) with non-zero mean
##
## Coefficients:
## mean
## 749.2778
## s.e. 71.7515
##
## sigma^2 = 98120: log likelihood = -128.47
## AIC=260.94 AICc=261.74 BIC=262.72
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set -1.642251e-13 304.4149 247.6728 -15.83767 36.80429 0.6671322
## ACF1
## Training set 0.2699253
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,0) with non-zero mean
## Q* = 2.5665, df = 4, p-value = 0.6328
##
## Model df: 0. Total lags used: 4
# Seleciona os valores de 2026.1 e 2026.2
valores_2026 <- previsao_ead$mean[2:3]
media_ead_2026 <- mean(valores_2026)
print(valores_2026)
## [1] 749.2778 749.2778
## [1] 749.2778
Por que a previsão ARIMA está constante?
O modelo ajustado foi um ARIMA(0,1,1) — um modelo de diferença com média móvel simples, sem termos autoregressivos, e isso tem implicações:
Esse tipo de modelo projeta uma tendência “neutra”, assumindo que as variações futuras serão semelhantes à média dos erros passados.
Como o modelo não tem componente autoregressivo (AR) nem tendência explícita (drift), ele não gera trajetória crescente ou decrescente.
Resultado: após o último valor da série, ele mantém a previsão constante, com bandas de incerteza que aumentam ao longo do horizonte.
Alternativamente, ajustamos um modelo ARIMA com drift:
## Series: graduacao_EAD
## ARIMA(0,1,1) with drift
##
## Coefficients:
## ma1 drift
## -1.0000 27.2632
## s.e. 0.1832 12.6035
##
## sigma^2 = 87196: log likelihood = -121.2
## AIC=248.4 AICc=250.24 BIC=250.9
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set -3.932745 269.5618 204.1392 -11.69672 28.15779 0.54987 0.1075065
valores_2026_drift <- previsao_drift$mean[2:3]
media_2026_drift <- mean(valores_2026_drift)
print(ceiling(media_2026_drift))
## [1] 1050
Optamos por utilizar o valor previsto pelo modelo do auto.arima, isto é \(749.2778\).
Mestrado
Para o mestrado, temos observações anuais de 2016 até 2025. Como são somente 10 observações, vamos ajustar um modelo de regressão linear simples para prever o valor para 2026. Optamos pelo modelo de regressão pelos seguintes motivos:
- Captura tendência crescente de forma direta.
- Menos parâmetros do que ARIMA.
- Funciona bem para séries pequenas com padrão linear.
# Dados -------------------------------------------------------------------
stricto_sensu <- read_excel("dados/Dados do Anuário.xlsx",
sheet = "Pós-Graduação Stricto Sensu",
col_types = c("numeric", "text", "text",
"text", "text", "skip", "numeric",
"skip", "skip"))
mestrado_2025 = tibble(Ano=2025, Matriculados = 4914)
stricto_sensu %>% filter(Nível %in% c("Mestrado Acadêmico",
"Mestrado Profissional")) %>%
group_by(Ano) %>%
summarise(Matriculados = sum(Matriculado)) %>%
bind_rows(mestrado_2025) -> mestrado
# Dados originais
anos <- 2016:2025
matriculados <- c(4609, 4541, 4745, 4804, 4818, 4999, 5278, 5297, 5370, 4914)
# Ajuste da regressão linear
modelo_lm <- lm(matriculados ~ anos)
# Criar novo conjunto de dados com os anos que queremos prever
novos_anos <- data.frame(anos = c(2025, 2026))
# Gerar previsões apenas para 2025 e 2026
previsoes <- predict(modelo_lm, newdata = novos_anos)
# Ver resultados
# print(previsoes)
# comparando com o ARIMA com drift:
# ts_mestrado <- ts(matriculados, start = 2016, frequency = 1)
# modelo_drift <- Arima(ts_mestrado, order = c(0,1,1), include.drift = TRUE)
# previsao_mestrado <- forecast(modelo_drift, h = 2)
#
previsao_mestrado_LINEAR_MODEL = previsoes[2]
# previsao_mestrado_ARIMA_DRIFT = previsao_mestrado$mean[2]
ceiling(previsao_mestrado_LINEAR_MODEL)
## 2
## 5368
Obtemos o valor previsto de \(5368\) alunos no mestrado para o ano de 2026.
Doutorado
Para o doutorado, novamente temos 10 observações. Por ser uma série muito “curta”, vamos utilizar novamente a regressão simples como método de predição.
doutorado_2025 = tibble(Ano=2025, Matriculados = 3363)
stricto_sensu %>% filter(Nível %in% c("Doutorado Acadêmico",
"Doutorado Profissional")) %>%
group_by(Ano) %>%
summarise(Matriculados = sum(Matriculado)) %>%
bind_rows(doutorado_2025) -> doutorado
# Dados
anos <- 2016:2025
matriculados <- c(3824, 3914, 3916, 3932, 4006, 4152, 4351, 4308, 4296, 3363)
# Ajuste do modelo linear
modelo_lm_doutorado <- lm(matriculados ~ anos)
summary(modelo_lm_doutorado)
##
## Call:
## lm(formula = matriculados ~ anos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -694.69 -60.45 -23.32 222.33 327.64
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -19113.22 69167.98 -0.276 0.789
## anos 11.44 34.23 0.334 0.747
##
## Residual standard error: 310.9 on 8 degrees of freedom
## Multiple R-squared: 0.01377, Adjusted R-squared: -0.1095
## F-statistic: 0.1117 on 1 and 8 DF, p-value: 0.7468
# Previsões para 2025 e 2026
novos_anos <- data.frame(anos = 2026)
previsoes_lm <- predict(modelo_lm_doutorado, newdata = novos_anos)
# Resultados
print(ceiling(previsoes_lm[1]))
## 1
## 4070
# ARIMA com drift
# ts_doutorado <- ts(matriculados, start = 2016, frequency = 1)
# modelo_drift_doutorado <- Arima(ts_doutorado, order = c(0,1,1), include.drift = TRUE)
# forecast_doutorado <- forecast(modelo_drift_doutorado, h = 1)
#
# autoplot(forecast_doutorado)
# print(ceiling(forecast_doutorado))
Assim, obtemos o valor predito para 2026 de \(4070\) alunos matriculados no doutorado.
Total de Alunos (Soma)
Temos, portanto, a predição para o total de alunos em 2026:
data.frame(grad_presencial = ceiling(media_2026),
grad_EAD = ceiling(media_ead_2026),
mestrado = ceiling(previsoes[2]),
doutorado = ceiling(previsoes_lm[1])) %>%
mutate(Total =
sum(grad_presencial, grad_EAD, mestrado, doutorado)) %>%
select("Graduação Presencial" = grad_presencial,
"Graduação a Distância" = grad_EAD,
"Mestrado" = mestrado,
"Doutorado" = doutorado,
Total)-> resultado_final
resultado_final %>% reactable(bordered = TRUE, striped = TRUE,
highlight = TRUE, rownames = FALSE)