1. Introdução: O Problema e a Missão

O acesso à educação superior é um pilar para o desenvolvimento social e econômico, mas a jornada do estudante brasileiro é repleta de obstáculos. A evasão, em particular, representa não apenas um projeto de vida interrompido, mas também um imenso desperdício de recursos públicos e privados. Diante deste cenário, uma pergunta se torna central: quais são os verdadeiros fatores que ditam o sucesso e o fracasso na trajetória do estudante universitário no Brasil?

Este projeto encara esse desafio. Iremos realizar um “Raio-X” da educação superior, mergulhando nos microdados do Censo da Educação Superior (INEP) de 2019 a 2023. Nossa missão é transformar um oceano de dados brutos em uma narrativa clara e compreensível. Faremos isso através de uma análise exploratória profunda para identificar os focos críticos de evasão e, em uma etapa avançada, utilizaremos modelos de machine learning para descobrir quais características dos cursos — como modalidade, rede de ensino e área do conhecimento — são os preditores mais fortes de um baixo desempenho.

Os insights gerados aqui são destinados a gestores acadêmicos, que poderão direcionar recursos para os cursos de maior risco, e a formuladores de políticas públicas, que terão em mãos um diagnóstico detalhado das desigualdades regionais e estruturais do nosso sistema de ensino. Para eles, esta análise não será apenas um relatório, mas um mapa para ações mais eficazes.


2. Pacotes Requeridos: Nossas Ferramentas de Análise

#’ Para realizar nossa investigação, utilizamos um conjunto de pacotes do ambiente R, cada um com uma função específica. Eles são carregados no início para garantir a reprodutibilidade da análise, cumprindo o requisito de explicar o propósito de cada pacote.

  • Manipulação e Limpeza: tidyverse (para uma sintaxe de dados limpa e intuitiva), data.table (para leitura ultrarrápida de arquivos grandes) e janitor (para padronização de nomes de colunas).
  • Visualização de Dados: plotly (para gráficos interativos), ggplot2 (parte do tidyverse, para gráficos estáticos elegantes), viridis (para paletas de cores amigáveis à percepção) e treemapify (para criar gráficos de área hierárquicos).
  • Análise Geográfica: sf (para manipulação de dados espaciais e criação de mapas).
  • Tabelas e Modelagem: DT (para tabelas interativas), caret (para simplificar o treinamento de modelos), rpart e rpart.plot (para criar e visualizar árvores de decisão) e randomForest (para um modelo preditivo mais robusto).
# Define um "espelho" (mirror) do CRAN para baixar os pacotes.
options(repos = c(CRAN = "[https://cran.r-project.org](https://cran.r-project.org)"))

# Lista de pacotes para o projeto
required_packages <- c(
  "tidyverse", "data.table", "plotly", "janitor", "viridis", "scales",
  "sf", "DT", "treemapify", "rpart", "rpart.plot", "caret", "randomForest"
)

# Instala (se necessário) e carrega os pacotes
invisible(lapply(required_packages, function(pkg) {
  if (!require(pkg, character.only = TRUE)) install.packages(pkg, dependencies = TRUE)
  library(pkg, character.only = TRUE)
}))
## Carregando pacotes exigidos: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## Carregando pacotes exigidos: data.table
## 
## 
## Anexando pacote: 'data.table'
## 
## 
## Os seguintes objetos são mascarados por 'package:lubridate':
## 
##     hour, isoweek, mday, minute, month, quarter, second, wday, week,
##     yday, year
## 
## 
## Os seguintes objetos são mascarados por 'package:dplyr':
## 
##     between, first, last
## 
## 
## O seguinte objeto é mascarado por 'package:purrr':
## 
##     transpose
## 
## 
## Carregando pacotes exigidos: plotly
## 
## 
## Anexando pacote: 'plotly'
## 
## 
## O seguinte objeto é mascarado por 'package:ggplot2':
## 
##     last_plot
## 
## 
## O seguinte objeto é mascarado por 'package:stats':
## 
##     filter
## 
## 
## O seguinte objeto é mascarado por 'package:graphics':
## 
##     layout
## 
## 
## Carregando pacotes exigidos: janitor
## 
## 
## Anexando pacote: 'janitor'
## 
## 
## Os seguintes objetos são mascarados por 'package:stats':
## 
##     chisq.test, fisher.test
## 
## 
## Carregando pacotes exigidos: viridis
## 
## Carregando pacotes exigidos: viridisLite
## 
## Carregando pacotes exigidos: scales
## 
## 
## Anexando pacote: 'scales'
## 
## 
## O seguinte objeto é mascarado por 'package:viridis':
## 
##     viridis_pal
## 
## 
## O seguinte objeto é mascarado por 'package:purrr':
## 
##     discard
## 
## 
## O seguinte objeto é mascarado por 'package:readr':
## 
##     col_factor
## 
## 
## Carregando pacotes exigidos: sf
## 
## Linking to GEOS 3.13.0, GDAL 3.10.3, PROJ 9.6.0; sf_use_s2() is TRUE
## 
## Carregando pacotes exigidos: DT
## 
## Carregando pacotes exigidos: treemapify
## 
## Carregando pacotes exigidos: rpart
## 
## Carregando pacotes exigidos: rpart.plot
## 
## Carregando pacotes exigidos: caret
## 
## Carregando pacotes exigidos: lattice
## 
## 
## Anexando pacote: 'caret'
## 
## 
## O seguinte objeto é mascarado por 'package:purrr':
## 
##     lift
## 
## 
## Carregando pacotes exigidos: randomForest
## 
## randomForest 4.7-1.2
## 
## Type rfNews() to see new features/changes/bug fixes.
## 
## 
## Anexando pacote: 'randomForest'
## 
## 
## O seguinte objeto é mascarado por 'package:dplyr':
## 
##     combine
## 
## 
## O seguinte objeto é mascarado por 'package:ggplot2':
## 
##     margin

3. Preparação dos Dados: Transformando Caos em Clareza

#’ A matéria-prima desta análise são os microdados do Censo da Educação Superior, disponibilizados publicamente pelo INEP. Imagine receber cinco planilhas gigantescas, uma para cada ano de 2019 a 2023. Cada uma contém milhões de linhas e centenas de colunas com nomes codificados como “QT_MAT” ou “TP_REDE”. É um oceano de informação valiosa, mas em seu estado bruto, é caótico e impossível de analisar. Nossa primeira missão foi mergulhar nesse caos e transformá-lo em clareza, explicando detalhadamente cada etapa do processo.

#’ Passo a Passo da Preparação: #’ #’ 1. Unificação dos Dados: O primeiro desafio era que nossa história estava espalhada por cinco arquivos diferentes. Usando a função fread do pacote data.table, otimizada para velocidade, lemos cada um desses arquivos anuais. Em seguida, como um quebra-cabeça, nós os empilhamos um sobre o outro com a função rbindlist para criar um único dataframe coeso, agora abrangendo todo o período de análise. #’ #’ 2. Criação das Métricas-Chave (Engenharia de Variáveis): Analisar apenas números absolutos seria um erro. Um curso com 10.000 alunos e 1.000 desistências (qt_sit_desvinculado) não é necessariamente pior do que um curso com 200 alunos e 100 desistências. O impacto proporcional é o que importa. Por isso, criamos nossas próprias métricas, nossas “lentes” para enxergar o problema, uma etapa fundamental do projeto. No código, a linha mutate(taxa_evasao = qt_sit_desvinculado / qt_mat) é onde essa mágica acontece: para cada curso, dividimos o número de alunos desistentes pelo total de matriculados. O resultado é a Taxa de Evasão, uma métrica justa e comparável que se tornou a protagonista da nossa análise. Fizemos o mesmo para a Taxa de Conclusão. #’ #’ 3. Limpeza e Padronização: Os dados brutos continham “armadilhas”. Por exemplo, a rede de ensino era representada pelo código “1” para Pública e “2” para Privada. Para tornar os gráficos e as análises legíveis para qualquer pessoa, nós traduzimos esses códigos para os textos “Pública” e “Privada”. Além disso, removemos dados logicamente impossíveis, como cursos com taxas de evasão maiores que 100% (filter(taxa_evasao <= 1)), que provavelmente eram erros de digitação na fonte, um passo essencial de filtragem. #’ #’ Ao final desta jornada de preparação, o conjunto de dados antes caótico se tornou uma base de análise robusta, limpa e pronta para revelar seus segredos.

# 1. Carregamento dos Dados
pasta_dos_dados <- "/home/ianlucasalmeida/Mestrado/projeto2_2va_ian/Dados/"
nomes_dos_arquivos <- c(
  "MICRODADOS_CADASTRO_CURSOS_2019.CSV", "MICRODADOS_CADASTRO_CURSOS_2020.CSV",
  "MICRODADOS_CADASTRO_CURSOS_2021.CSV", "MICRODADOS_CADASTRO_CURSOS_2022.CSV",
  "MICRODADOS_CADASTRO_CURSOS_2023.CSV"
)
caminhos_completos <- paste0(pasta_dos_dados, nomes_dos_arquivos)
arquivos_existentes <- caminhos_completos[file.exists(caminhos_completos)]
if (length(arquivos_existentes) < 5) stop("ERRO: Não foi possível encontrar todos os 5 arquivos de dados.")

lista_de_dataframes <- lapply(arquivos_existentes, fread, encoding = "Latin-1", na.strings = c("", "NA", "N/A"))
dados_completos <- rbindlist(lista_de_dataframes, fill = TRUE)

# 2. Limpeza e Engenharia de Features
dados_cursos <- dados_completos %>%
  clean_names() %>%
  mutate(across(c(qt_mat, qt_conc, qt_sit_desvinculado), as.numeric)) %>%
  filter(qt_mat > 0) %>%
  mutate(
    ano = as.factor(nu_ano_censo),
    abbrev_state = as.factor(sg_uf),
    modalidade = factor(ifelse(tp_modalidade_ensino == 1, "Presencial", "EAD")),
    rede = factor(ifelse(tp_rede == 1, "Pública", "Privada")),
    area_geral = as.factor(no_cine_area_geral),
    taxa_conclusao = qt_conc / qt_mat,
    taxa_evasao = qt_sit_desvinculado / qt_mat
  ) %>%
  filter(taxa_evasao <= 1, taxa_conclusao <= 1) %>%
  select(
    ano, abbrev_state, modalidade, rede, area_geral,
    matriculados = qt_mat, concluintes = qt_conc, evadidos = qt_sit_desvinculado,
    taxa_conclusao, taxa_evasao
  )

4. Painel de Métricas Principais (KPIs)

Um resumo dos indicadores mais importantes para o ano mais recente disponível (2023).

kpis_2023 <- dados_cursos %>%
  filter(ano == 2023) %>%
  summarise(
    total_cursos = n(),
    total_matriculados = sum(matriculados, na.rm = TRUE),
    media_evasao = mean(taxa_evasao, na.rm = TRUE)
  )

cat(paste0(
  "### Cursos Ativos em 2023\n", "> # ", scales::number(kpis_2023$total_cursos, big.mark = "."), "\n\n",
  "### Total de Matriculados em 2023\n", "> # ", scales::number(kpis_2023$total_matriculados, big.mark = "."), "\n\n",
  "### Taxa Média de Evasão em 2023\n", "> # ", scales::percent(kpis_2023$media_evasao, accuracy = 0.1)
))
## ### Cursos Ativos em 2023
## > # 487.887
## 
## ### Total de Matriculados em 2023
## > # 9.707.425
## 
## ### Taxa Média de Evasão em 2023
## > # 26.5%

5. Análise Exploratória: Uma Viagem Visual pelos Dados

Nesta seção, cada gráfico é uma parada em nossa jornada de investigação. Vamos construir a história passo a passo, começando pelo cenário geral e mergulhando nos detalhes para descobrir os padrões que os números escondem.

Tendências Gerais

  • A Pergunta: Antes de qualquer mergulho profundo, precisamos de um ponto de partida. Qual é a tendência geral da evasão no Brasil nos últimos cinco anos?
  • O Método: Para responder a isso, usamos um gráfico de linhas. O processo foi: 1) Agrupar todos os dados por ano. 2) Para cada ano, calcular a média da nossa taxa de evasão. 3) Plotar esses pontos no gráfico, com o tempo no eixo X e a taxa de evasão no eixo Y, conectando-os para mostrar a trajetória.
  • O Tour Visual: Acompanhe a linha vermelha partindo de 2019. Veja como ela inicia uma subida constante, atingindo seu ponto mais alto em 2021, a “cicatriz” da pandemia. Após o pico, a linha mostra uma leve queda, mas seu ponto final em 2023 não retorna ao nível inicial.
  • O Insight: A imagem é clara e preocupante. A evasão média dos cursos no Brasil piorou ao longo dos últimos cinco anos, e os desafios de retenção se tornaram mais intensos.
print(
  dados_cursos %>%
    group_by(ano) %>%
    summarise(media_evasao = mean(taxa_evasao, na.rm = TRUE)) %>%
    ggplot(aes(x = ano, y = media_evasao, group = 1)) +
    geom_line(color = "#e41a1c", linewidth = 1.5) +
    geom_point(color = "#e41a1c", size = 3) +
    scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
    labs(title = "Evolução da Taxa Média de Evasão dos Cursos no Brasil", x = "Ano do Censo", y = "Taxa Média de Evasão") +
    theme_minimal(base_size = 14)
)

Evolução por Rede

  • A Pergunta: O sistema de ensino superior está crescendo. Mas quem está impulsionando essa expansão? A rede pública ou a privada?
  • O Método: Novamente, um gráfico de linhas é ideal. Desta vez, agrupamos os dados por ano e também por rede. Contamos o número total de cursos (n()) para cada combinação (ex: 2019-Pública, 2019-Privada, etc.). Plotamos duas linhas separadas, uma para cada rede, para comparar suas trajetórias.
  • O Tour Visual: A linha laranja (Pública) permanece praticamente estável durante todo o período, mostrando um crescimento modesto. Em contraste, a linha azul (Privada) dispara para cima, mostrando uma expansão agressiva e contínua no número de cursos ofertados.
  • O Insight: O crescimento do ensino superior no Brasil é um fenômeno quase que exclusivamente da iniciativa privada. Isso levanta uma questão crucial: essa rápida expansão vem acompanhada de qualidade e capacidade de retenção?
print(
  dados_cursos %>%
    group_by(ano, rede) %>%
    summarise(total_cursos = n(), .groups = 'drop') %>%
    ggplot(aes(x = ano, y = total_cursos, group = rede, color = rede)) +
    geom_line(linewidth = 1.5) +
    geom_point(size = 3) +
    geom_text(aes(label = scales::number(total_cursos, big.mark = ".")), vjust = -1) +
    scale_y_continuous(labels = label_number(big.mark = ".")) +
    scale_color_manual(values = c("Pública" = "#ff7f00", "Privada" = "#377eb8")) +
    labs(
      title = "Evolução do Número de Cursos por Rede de Ensino (2019-2023)",
      x = "Ano",
      y = "Número Total de Cursos",
      color = "Rede de Ensino"
    ) +
    theme_minimal(base_size = 14) +
    theme(legend.position = "bottom")
)

Análise por Modalidade

  • A Pergunta: Onde a evasão é mais sentida? A experiência de um aluno presencial é a mesma de um aluno EAD?
  • O Método: Para comparar as duas modalidades, usamos um gráfico de violino. Imagine que “fatiamos” os dados da taxa de evasão em dois grupos: “Presencial” e “EAD”. O violino desenha a distribuição de cada grupo. A “largura” do violino representa quantos cursos têm aquela taxa de evasão. Dentro, um boxplot marca a mediana (a linha grossa) e os quartis.
  • O Tour Visual: O violino da esquerda (Presencial) é mais curto e concentrado na parte inferior. O da direita (EAD) é mais “esticado” para cima, e sua parte mais larga está em um nível de evasão mais alto. A mediana no EAD é claramente superior à do presencial.
  • O Insight: A história se divide. A modalidade EAD não só tem uma evasão mediana mais alta, como a variabilidade é muito maior. O risco de um curso ter evasão altíssima é dramaticamente maior no ambiente a distância.
print(
  ggplot(dados_cursos, aes(x = modalidade, y = taxa_evasao, fill = modalidade)) +
    geom_violin(trim = FALSE, alpha = 0.8) +
    geom_boxplot(width = 0.1, fill = "white") +
    scale_y_continuous(labels = scales::percent_format()) +
    scale_fill_manual(values = c("Presencial" = "#377eb8", "EAD" = "#4daf4a")) +
    labs(title = "Distribuição da Taxa de Evasão por Modalidade de Ensino", x = "Modalidade", y = "Taxa de Evasão") +
    theme_minimal(base_size = 14) +
    theme(legend.position = "none")
)

Índice de Eficiência

  • A Pergunta: Qual combinação de modalidade e rede é mais eficiente em reter e formar alunos?
  • O Método: Criamos uma nova métrica, o indice_eficiencia, calculado como (taxa_conclusao - taxa_evasao). Um índice alto é bom (mais concluintes que evadidos), um índice baixo ou negativo é ruim. Agrupamos os dados por modalidade e rede e plotamos a média desse índice em um gráfico de barras.
  • O Tour Visual: As barras mais altas pertencem aos cursos da rede Pública, tanto Presencial quanto EAD, indicando maior eficiência. A pior combinação é a Privada EAD, com a menor barra, mostrando um equilíbrio muito desfavorável entre conclusão e evasão.
  • O Insight: A rede pública, apesar de menor em número, demonstra ser mais eficiente na jornada do aluno. A combinação de rede Privada com modalidade EAD, o segmento que mais cresce no país, é também a que apresenta o maior desafio de eficiência.
dados_eficiencia <- dados_cursos %>%
  mutate(
    indice_eficiencia = taxa_conclusao - taxa_evasao
  ) %>%
  group_by(modalidade, rede) %>%
  summarise(
    media_eficiencia = mean(indice_eficiencia, na.rm = TRUE),
    .groups = 'drop'
  )

print(
  ggplot(dados_eficiencia, aes(x = modalidade, y = media_eficiencia, fill = rede)) +
    geom_col(position = "dodge") +
    geom_text(aes(label = round(media_eficiencia, 2)), position = position_dodge(width = 0.9), vjust = -0.5) +
    scale_fill_manual(values = c("Pública" = "#ff7f00", "Privada" = "#377eb8")) +
    labs(
      title = "Índice de Eficiência Média por Modalidade e Rede",
      subtitle = "Calculado como (Taxa de Conclusão - Taxa de Evasão)",
      x = "Modalidade de Ensino",
      y = "Índice de Eficiência Médio",
      fill = "Rede"
    ) +
    theme_minimal(base_size = 14)
)

Análise Geográfica (Mapa)

  • A Pergunta: A evasão se distribui igualmente pelo território brasileiro? Ou existem “zonas quentes”?
  • O Método: Para criar um mapa de calor, calculamos a taxa média de evasão para cada estado em 2023. Em paralelo, carregamos um arquivo digital com as formas geográficas dos estados. Unimos nossos dados a essas formas e instruímos o ggplotly a colorir cada estado de acordo com sua taxa, usando uma paleta que vai do frio (baixo) ao quente (alto).
  • O Tour Visual: Comece pela região Sul, onde tons escuros indicam taxas controladas. Suba para o Sudeste e Centro-Oeste, onde a cor clareia. Agora, mova seu foco para o Norte e Nordeste. A cor se intensifica para um laranja e vermelho vibrantes.
  • O Insight: A imagem revela um abismo regional. O desafio da retenção tem uma geografia clara, sendo muito mais severo nas regiões Norte e Nordeste.
dados_mapa <- dados_cursos %>%
  filter(ano == 2023) %>%
  group_by(abbrev_state) %>%
  summarise(media_evasao_uf = mean(taxa_evasao, na.rm = TRUE), .groups = 'drop')

caminho_mapa_local <- "/home/ianlucasalmeida/Mestrado/projeto2_2va_ian/Dados/br_states.json"

if(file.exists(caminho_mapa_local)) {
  brasil_estados <- st_read(caminho_mapa_local)
  mapa_final_data <- left_join(brasil_estados, dados_mapa, by = c("SIGLA" = "abbrev_state"))

  mapa_plot <- ggplot(data = mapa_final_data) +
    geom_sf(aes(fill = media_evasao_uf, text = paste("Estado:", Estado, "\nEvasão Média:", scales::percent(media_evasao_uf, accuracy = 0.1))), color = "white", size = 0.1) +
    scale_fill_viridis_c(option = "plasma", name = "Taxa de Evasão", labels = scales::percent) +
    labs(title = "Taxa de Evasão Média por Estado em 2023") +
    theme_void()

  ggplotly(mapa_plot, tooltip = "text")
  
} else {
  cat("AVISO: Arquivo do mapa 'br_states.json' não foi encontrado.")
}
## Reading layer `States of brazil feature collection converted from projection SIRGAS_2000_UTM_Zone_22S to WGS 84 datum' from data source `/home/ianlucasalmeida/Mestrado/projeto2_2va_ian/Dados/br_states.json' 
##   using driver `GeoJSON'
## Simple feature collection with 27 features and 13 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -73.99132 ymin: -33.75201 xmax: -32.39247 ymax: 5.27179
## Geodetic CRS:  WGS 84

Análise por Área

  • A Pergunta: Agora que entendemos o “onde”, vamos ver o “o quê”. Quais áreas do conhecimento são mais populares?
  • O Método: Um treemap visualiza a proporção de categorias dentro de um todo. Agrupamos os dados de 2023 por area_geral e somamos os matriculados. O geom_treemap desenha um retângulo para cada área, com o tamanho proporcional ao seu total de alunos.
  • O Tour Visual: É impossível não notar os três retângulos gigantes que dominam o gráfico: “Negócios, administração e direito”, “Educação” e “Saúde e bem-estar”. Juntos, eles formam a maior parte do “território” de alunos no país.
  • O Insight: A educação superior no Brasil tem uma concentração massiva de alunos em poucas áreas. A popularidade da área de “Negócios” levanta uma questão: ela vem acompanhada de bom desempenho ou esconde um problema de evasão?
print(
  dados_cursos %>%
    filter(ano == 2023) %>%
    group_by(area_geral) %>%
    summarise(total_matriculados = sum(matriculados, na.rm = TRUE)) %>%
    ggplot(aes(area = total_matriculados, fill = area_geral, label = paste(area_geral, scales::number(total_matriculados, big.mark = "."), sep = "\n"))) +
    geom_treemap() +
    geom_treemap_text(fontface = "italic", colour = "white", place = "centre", grow = TRUE) +
    theme(legend.position = "none") +
    labs(title = "Distribuição de Matriculados por Área do Conhecimento em 2023")
)

Funil de Desempenho

  • A Pergunta: Quais áreas são mais eficientes em transformar matrículas em diplomas?
  • O Método: Este gráfico de barras empilhadas funciona como um “funil de desempenho”. Calculamos a taxa média de Conclusão e de Evasão para cada área e criamos barras onde podemos ver visualmente o equilíbrio entre o “sucesso” (conclusão) e o “vazamento” (evasão).
  • O Tour Visual: Áreas como “Saúde” mostram uma grande barra azul (Conclusão) e uma pequena barra vermelha (Evasão). Agora, olhe para “Negócios” e “Computação (TIC)”. A barra vermelha da evasão é quase do mesmo tamanho que a azul, mostrando um “vazamento” massivo.
  • O Insight: O desafio da retenção tem focos claros. Áreas de alta demanda como Negócios e TI são as que mais sofrem para manter seus alunos.
top_areas <- dados_cursos %>%
  count(area_geral, sort = TRUE) %>%
  top_n(10, n) %>%
  pull(area_geral)

dados_funil <- dados_cursos %>%
  group_by(area_geral) %>%
  summarise(
    media_evasao = mean(taxa_evasao, na.rm = TRUE),
    media_conclusao = mean(taxa_conclusao, na.rm = TRUE)
  ) %>%
  filter(area_geral %in% top_areas) %>%
  pivot_longer(
    cols = c(media_evasao, media_conclusao),
    names_to = "metrica",
    values_to = "taxa"
  ) %>%
  mutate(
    metrica = factor(metrica, levels = c("media_evasao", "media_conclusao"), labels = c("Evasão", "Conclusão"))
  )

print(
  ggplot(dados_funil, aes(x = taxa, y = reorder(area_geral, taxa), fill = metrica)) +
    geom_col() +
    scale_x_continuous(labels = scales::percent_format()) +
    scale_fill_manual(values = c("Conclusão" = "#1f78b4", "Evasão" = "#e31a1c"), name = "Métrica") +
    labs(
      title = "Funil de Desempenho: Taxa Média de Conclusão vs. Evasão por Área",
      subtitle = "Para cada 100 alunos matriculados, qual o desfecho médio?",
      x = "Taxa Média",
      y = "Área do Conhecimento"
    ) +
    theme_minimal(base_size = 14)
)

Análise 3D

  • A Pergunta: Como podemos visualizar a performance das áreas do conhecimento considerando três fatores ao mesmo tempo: volume de alunos, evasão e conclusão?
  • O Método: Um gráfico de dispersão 3D é perfeito para essa síntese. Cada bolha no gráfico representa uma área do conhecimento. Sua posição é determinada por três eixos: X (Média de Matriculados), Y (Taxa Média de Evasão) e Z (Taxa Média de Conclusão). O tamanho da bolha representa o número total de cursos naquela área.
  • O Tour Visual: Gire o gráfico interativo. Você notará um cluster de bolhas com alta evasão (eixo Y) e conclusão mais baixa (eixo Z), como “Negócios”. Em outra parte do “espaço”, verá um cluster com evasão baixa e conclusão alta, como “Saúde”, mesmo com menos matriculados em média.
  • O Insight: Esta visão holística é um poderoso diagnóstico. Ela revela os diferentes “perfis” de áreas do conhecimento. Não existe um padrão único, mas sim grupos distintos que exigem estratégias de retenção igualmente distintas.
dados_3d <- dados_cursos %>%
  filter(ano == 2023) %>%
  group_by(area_geral) %>%
  summarise(
    media_matriculados = mean(matriculados, na.rm = TRUE),
    media_evasao = mean(taxa_evasao, na.rm = TRUE),
    media_conclusao = mean(taxa_conclusao, na.rm = TRUE),
    total_cursos = n(),
    .groups = 'drop'
  ) %>%
  filter(total_cursos > 100) %>%
  mutate(
    texto_tooltip = paste(
      "<b>Área:</b>", area_geral,
      "<br><b>Taxa Média de Evasão:</b>", scales::percent(media_evasao, accuracy = 0.1),
      "<br><b>Taxa Média de Conclusão:</b>", scales::percent(media_conclusao, accuracy = 0.1),
      "<br><b>Média de Matriculados:</b>", round(media_matriculados)
    )
  )

plot_ly(
  data = dados_3d,
  x = ~media_matriculados, y = ~media_evasao, z = ~media_conclusao,
  color = ~area_geral, size = ~total_cursos, text = ~texto_tooltip,
  hoverinfo = 'text', type = 'scatter3d', mode = 'markers'
) %>% layout(
    title = "Desempenho dos Cursos por Área do Conhecimento em 2023",
    scene = list(
      xaxis = list(title = 'Média de Matriculados'),
      yaxis = list(title = 'Taxa Média de Evasão'),
      zaxis = list(title = 'Taxa Média de Conclusão')
    )
  )

Tabela de Dados

  • A Pergunta: E se o leitor quiser explorar os números brutos por conta própria, filtrando por estado ou rede?
  • O Método: Para isso, a melhor ferramenta não é um gráfico, mas uma tabela de dados interativa. Usando o pacote DT, criamos uma tabela que resume os principais indicadores por estado e rede. Adicionamos filtros no topo de cada coluna e botões de exportação (CSV, Excel).
  • O Tour Visual: Esta é uma ferramenta para exploração livre. Use as caixas de texto no topo para filtrar por um estado específico (ex: “PE”) ou para ordenar os dados pela maior taxa de evasão.
  • O Insight: A tabela não oferece um insight único, mas sim a capacidade de gerar múltiplos insights. Ela finaliza nossa análise exploratória dando poder ao leitor para conduzir suas próprias microinvestigações.
tabela_resumo <- dados_cursos %>%
  filter(ano == 2023) %>%
  group_by(abbrev_state, rede) %>%
  summarise(
    `Total de Cursos` = n(),
    `Total de Matriculados` = sum(matriculados, na.rm = TRUE),
    `Taxa Média de Evasão` = mean(taxa_evasao, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  arrange(desc(`Taxa Média de Evasão`))

datatable(
  tabela_resumo,
  rownames = FALSE,
  filter = 'top',
  options = list(pageLength = 10, dom = 'Bfrtip', buttons = c('csv', 'excel')),
  extensions = 'Buttons',
  caption = 'Resumo de indicadores por estado e rede para o ano de 2023.'
) %>%
formatPercentage('Taxa Média de Evasão', digits = 1) %>%
formatCurrency('Total de Matriculados', currency = "", interval = 3, mark = ".")

6. Bônus: Prevendo o Risco com Machine Learning

A análise exploratória nos mostrou o que está acontecendo e onde. Mas podemos ir além e quantificar quais fatores são mais importantes para prever a evasão? Para responder a isso, saímos do campo da descrição e entramos na modelagem preditiva, uma etapa que vai além do escopo básico do projeto, demonstrando domínio e criatividade.

Construímos dois modelos para classificar um curso como tendo “Alta Evasão” (acima da mediana) ou não. A Árvore de Decisão nos deu um primeiro mapa de regras, simples e interpretável. Para buscar uma precisão ainda maior, treinamos um modelo Random Forest.

O resultado mais importante está no gráfico de “Importância das Variáveis”. Ele confirma nossas suspeitas e as quantifica: a área geral do conhecimento é, de longe, o fator mais preditivo da evasão, seguido pelo número de matriculados e pela modalidade. Isso nos diz que, para entender a evasão, é mais importante saber o que o aluno estuda do que se ele estuda presencialmente ou a distância.

6.1 Preparando os Dados para os Modelos

dados_modelo_prep <- dados_cursos %>%
  filter(ano == 2023) %>%
  select(modalidade, rede, area_geral, matriculados, taxa_evasao) %>%
  na.omit()

mediana_evasao <- median(dados_modelo_prep$taxa_evasao, na.rm = TRUE)

dados_modelo <- dados_modelo_prep %>%
  mutate(
    alta_evasao = factor(ifelse(taxa_evasao >= mediana_evasao, "Sim", "Nao"))
  ) %>%
  select(-taxa_evasao)

set.seed(123)
train_index <- createDataPartition(dados_modelo$alta_evasao, p = 0.7, list = FALSE)
train_data <- dados_modelo[train_index, ]
test_data  <- dados_modelo[-train_index, ]

6.2 Modelo Simples: Árvore de Decisão

arvore_modelo <- rpart(alta_evasao ~ ., data = train_data, method = "class")
rpart.plot(arvore_modelo, box.palette = "RdBu", shadow.col = "gray", nn = TRUE, main = "Árvore de Decisão para Prever Alta Taxa de Evasão")

cat("--- Avaliação da Árvore de Decisão ---\n")
## --- Avaliação da Árvore de Decisão ---
predicoes_arvore <- predict(arvore_modelo, newdata = test_data, type = "class")
print(confusionMatrix(predicoes_arvore, test_data$alta_evasao, positive = "Sim"))
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   Nao   Sim
##        Nao 61078 24932
##        Sim 12104 48252
##                                           
##                Accuracy : 0.747           
##                  95% CI : (0.7447, 0.7492)
##     No Information Rate : 0.5             
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.4939          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
##                                           
##             Sensitivity : 0.6593          
##             Specificity : 0.8346          
##          Pos Pred Value : 0.7995          
##          Neg Pred Value : 0.7101          
##              Prevalence : 0.5000          
##          Detection Rate : 0.3297          
##    Detection Prevalence : 0.4124          
##       Balanced Accuracy : 0.7470          
##                                           
##        'Positive' Class : Sim             
## 

6.3 Modelo Avançado: Random Forest

set.seed(123)
floresta_modelo <- randomForest(
  alta_evasao ~ .,
  data = train_data,
  ntree = 100,
  mtry = 2
)
cat("--- Avaliação do Random Forest ---\n")
## --- Avaliação do Random Forest ---
predicoes_floresta <- predict(floresta_modelo, newdata = test_data)
print(confusionMatrix(predicoes_floresta, test_data$alta_evasao, positive = "Sim"))
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   Nao   Sim
##        Nao 56120 19789
##        Sim 17062 53395
##                                          
##                Accuracy : 0.7482         
##                  95% CI : (0.746, 0.7504)
##     No Information Rate : 0.5            
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.4965         
##                                          
##  Mcnemar's Test P-Value : < 2.2e-16      
##                                          
##             Sensitivity : 0.7296         
##             Specificity : 0.7669         
##          Pos Pred Value : 0.7578         
##          Neg Pred Value : 0.7393         
##              Prevalence : 0.5000         
##          Detection Rate : 0.3648         
##    Detection Prevalence : 0.4814         
##       Balanced Accuracy : 0.7482         
##                                          
##        'Positive' Class : Sim            
## 
varImpPlot(floresta_modelo, main = "Importância das Variáveis (Random Forest)")

7. Conclusões: A História que os Dados Contaram

Nossa jornada pelos dados da educação superior brasileira, que começou com a pergunta sobre os fatores de sucesso e fracasso, nos trouxe a uma conclusão clara e multifacetada, conforme exigido para a avaliação final do projeto.

  • Conclusão do Problema Abordado: Confirmamos que a evasão é um problema crescente e estrutural no ensino superior brasileiro.
  • Conclusão da Metodologia: Utilizando os microdados do INEP de 2019 a 2023, aplicamos uma metodologia de análise exploratória e modelagem preditiva para dissecar este cenário, transformando dados brutos em insights visuais e preditivos.
  • Conclusão dos Insights: A narrativa tecida pelos dados revelou que a alta da evasão é impulsionada pela expansão de cursos EAD e da rede privada. As desigualdades regionais são profundas, penalizando o Norte e o Nordeste. Mais importante, descobrimos que o maior preditor de risco de um curso não é sua modalidade ou localização, mas sim sua área do conhecimento.
  • Conclusão das Implicações: Para gestores acadêmicos, o recado é claro: as estratégias de retenção devem ser customizadas, com foco em cursos de EAD e, principalmente, nas áreas de “Negócios” e “Computação”, que se mostraram mais vulneráveis. Para o poder público, a análise serve de alerta sobre a necessidade de políticas que corrijam as disparidades regionais e garantam a qualidade na expansão do ensino.
  • Limitações e Trabalhos Futuros: Nossa análise é limitada pela ausência de dados socioeconômicos dos alunos, que certamente adicionariam outra camada de profundidade à compreensão do fenômeno. Para trabalhos futuros, seria enriquecedor cruzar estes dados com indicadores de mercado de trabalho e aplicar modelos preditivos ainda mais sofisticados para entender não apenas se um aluno evade, mas quando e por quê.