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:

ggAcf(graduacao_presencial)

autoplot(diff(graduacao_presencial))

ggAcf(diff(graduacao_presencial))

autoplot(diff(graduacao_presencial, 2))

ggAcf(diff(graduacao_presencial, 2))

# estacionaria: o valor d=2 no autoarima

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:

# Calculando a média
media_2026 <- mean(valores_2026)
print(ceiling(media_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
# validacao do modelo
checkresiduals(modelo_ead)

## 
##  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
previsao_ead <- forecast(modelo_ead, h = 4)
autoplot(previsao_ead)

# 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
print(media_ead_2026)
## [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:

modelo_drift <- Arima(graduacao_EAD, order = c(0,1,1), include.drift = TRUE)
summary(modelo_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
previsao_drift <- forecast(modelo_drift, h = 3)
autoplot(previsao_drift)

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
#ceiling(previsao_mestrado_ARIMA_DRIFT)

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)