1 Introdução ao estudo

1.1 Introdução

Neste projeto, analiso a educação do município de Paulista–PE ao longo de oito anos, com dados coletados bienalmente. O objetivo é avaliar a evolução da rede municipal, identificar pontos críticos que afetam a qualidade do ensino e destacar escolas com melhores e piores desempenhos em Língua Portuguesa, Matemática e distorção idade-série. A relevância do estudo está em fornecer informações que subsidiem decisões e políticas educacionais mais eficazes, considerando também os impactos da pandemia na aprendizagem.

1.2 Metodologia

Serão analisadas 160 planilhas obtidas no portal QEdu, contendo dados detalhados de matrículas, aprovação, abandono, aprendizagem, fluxo escolar e outros indicadores. Embora o site do QEdu apresente análises gerais, meu objetivo é ir além: cruzar variáveis específicas, comparar escolas individualmente, reconstruir séries históricas limpas e calcular métricas que não aparecem prontas na plataforma, como somatórios reais de abandono, distorção agregada e evolução percentual por série. A metodologia envolve limpeza dos dados, criação de tabelas consolidadas e visualização gráfica para destacar pontos críticos e mudanças ao longo dos anos.

1.3 Proposta

Para enfrentar o problema, adoto uma análise quantitativa ano a ano usando um dataset extenso composto por todas as escolas públicas do município entre 2015 e 2023. A abordagem consiste em calcular indicadores-chave (aprovação, reprovação, abandono, distorção idade-série, matrículas, desempenho) e observar sua evolução ao longo do tempo, separando por série e consolidando por ano. Diferente das métricas agregadas do QEdu, que mostram apenas médias gerais, meu tratamento usa os microdados brutos de cada escola e soma ponderada dos valores. Isso permite identificar exatamente onde os piores índices se concentram — se em anos específicos, séries específicas ou escolas isoladas — e não apenas a média municipal. A técnica deve revelar padrões e gargalos que os indicadores oficiais, por serem muito resumidos, não deixam evidente.

1.4 Beneficiados

A análise ajuda gestores municipais, escolas e pesquisadores ao mostrar claramente onde estão os gargalos educacionais do município. Com indicadores separados por série, ano e comportamento ao longo do tempo, fica mais fácil priorizar políticas públicas, direcionar recursos e identificar quais intervenções são mais urgentes. O resultado permite decisões mais precisas, baseadas em dados concretos, e não apenas em percepções gerais ou médias agregadas que escondem problemas locais.

2 Pacotes

2.1 Pacotes utilizados.

# Pacote de funções 
library(tidyverse)

# Manipulação e limpeza
library(dplyr)
library(tidyr)
library(stringr)

# Leitura de dados
library(readr)
library(readxl)
library(scales)

# Visualização
library(ggplot2)
library(plotly)


# Organização do relatório
library(knitr)
library(rmarkdown)

knitr::opts_chunk$set(warning = FALSE)
pasta <- "C:/Users/davia/Downloads/analise/"

arquivos <- list.files(pasta, full.names = TRUE, pattern = "\\.csv$")

ler_csv_completo <- function(arq) {
  read_csv(arq, col_types = cols(.default = "c"))
}

dados_gerais <- arquivos %>%
  map_dfr(ler_csv_completo) %>%              # junta todos os CSVs
  mutate(across(everything(), ~ type.convert(., as.is = TRUE))) %>% 
  distinct() %>%                             # remove duplicados
  filter(!dependencia_id %in% c(1, 2, 4, 5)) # mantém só quem NÃO está nesses grupos

2.2 Propósito dos pacotes.

  • dplyr – usado para filtrar, agrupar, resumir e transformar dados de forma intuitiva. É o núcleo da manipulação.

  • tidyr – organiza dados desestruturados, facilita pivotagem, separação e junção de colunas, deixando tudo no formato “tidy”.

  • stringr – simplifica qualquer operação com textos, como padronizar nomes, extrair padrões ou corrigir inconsistências.

  • readr – leitura rápida e limpa de arquivos .csv, mantendo nomes de colunas e codificação corretos.

  • readxl – leitura de arquivos Excel sem precisar do Excel instalado, essencial para importar os dados originais.

  • ggplot2 – cria gráficos estáticos bem estruturados, com controle total sobre estética, cores, escalas e temas.

  • plotly – transforma gráficos em versões interativas (zoom, hover, seleção). Útil para dashboards e apresentações.

  • knitr – responsável pela renderização dos chunks, controle do código e aparência do relatório.

  • rmarkdown – converte o documento final em HTML, PDF ou Word e integra texto, tabelas e visualizações num único arquivo.

3 Tratamento dos dados

3.1 Fonte dos dados

Os dados utilizados neste trabalho foram obtidos no portal público QEdu, página do município Paulista, PE: https://qedu.org.br/municipio/2610707-paulista.
O portal disponibiliza os resultados dos indicadores educacionais divulgados pelo INEP — incluindo proficiências em Língua Portuguesa e Matemática, distorção idade-série, taxas de abandono, número de matrículas, entre outros — organizados por escola, ano e série.

3.2 Descrição detalhada dos dados.

Os dados originais foram obtidos a partir dos microconjuntos disponibilizados publicamente pelo INEP e organizados no portal QEdu. O propósito inicial desses dados é monitorar o desempenho e as condições da educação básica nas redes públicas do país, permitindo que gestores, pesquisadores e cidadãos acompanhem indicadores de aprendizado, fluxo escolar, infraestrutura e rendimento.
As informações foram coletadas em anos específicos — 2015, 2017, 2019, 2021 e 2023 — que são os ciclos de divulgação dos indicadores utilizados pelo INEP e também os anos para os quais o município de Paulista possui dados completos no portal. Cada ano apresenta um conjunto extenso de variáveis relacionadas a matrículas, aprovação, abandono, distorção idade-série, notas de Língua Portuguesa e Matemática, níveis de proficiência, infraestrutura escolar e características gerais das escolas.
O conjunto original possuía mais de 160 planilhas, cada uma contendo dezenas de variáveis. No dataset unificado, algumas variáveis apresentavam valores ausentes (NA), geralmente decorrentes de escolas que não ofertavam determinada série naquele ano, escolas pequenas sem estudantes suficientes para divulgar indicadores, ou simplesmente ausência de resposta no levantamento original. Esses NAs foram tratados de forma explícita durante a análise: removidos nos cálculos onde impossibilitariam médias ou somas, mas preservados quando representavam ausência real de dados.
Além disso, alguns indicadores vinham registrados em percentuais (0–100), enquanto outros apareciam como contagens absolutas (ex.: matrículas, aprovados, abandonos). A unificação exigiu cuidado para evitar somas incorretas de percentuais, sendo necessário padronizar cálculos (especialmente em distorção idade-série e abandono) com base na média ponderada pelas matrículas de cada escola.

3.3 Etapas de importação e limpeza dos dados.

Os dados originais foram baixados diretamente do portal QEdu em formato de planilhas. Como o site disponibiliza vários arquivos separados por ano e indicador, a primeira etapa foi converter todas essas planilhas para CSV, permitindo a importação automatizada no R. Em seguida, todos os CSVs foram unidos em um único grande dataset, mantendo a estrutura original.
Durante a montagem do dataset, a limpeza necessária foi mínima. Os arquivos não apresentavam erros estruturais, variáveis mal formatadas ou inconsistências graves. A principal ação de limpeza realizada foi remover valores NA quando estes impediam cálculos ou agregações. Não houve necessidade de recodificar variáveis ou corrigir erros de digitação.
Como cada arquivo segue um dicionário próprio, identifiquei as variáveis-chave para garantir que as análises fossem feitas sobre as escolas corretas. Entre elas, a mais importante foi o inep_id, que é o identificador único de cada escola no INEP. Sempre que precisei filtrar ou combinar informações, utilizei o inep_id para evitar erros de correspondência entre unidades escolares. Fora isso, os dados permaneceram no formato original fornecido pela fonte. ### Coleta focada na coluna inep_id que representa o número da escola no inep.

3.4 Visualização condensada do dataset final.

dados_gerais %>% 
  dplyr::sample_n(10) %>% 
  knitr::kable(caption = "Amostra de 10 linhas do conjunto de dados final após limpeza")
Amostra de 10 linhas do conjunto de dados final após limpeza
ano inep_id dependencia_id localizacao_id ef_1ano ef_2ano ef_3ano ef_4ano ef_5ano ef_6ano ef_7ano ef_8ano ef_9ano ef_total_ai ef_total_af ef_total em_1ano em_2ano em_3ano em_4ano em_total ibge_id ciclo_id ideb fluxo aprendizado nota_mt nota_lp lp_adequado mt_adequado lp_insuficiente lp_basico lp_proficiente lp_avancado mt_insuficiente mt_basico mt_proficiente mt_avancado matriculas serie_id aprovados reprovados abandonos Variável Descrição Códigos
2017 26116260 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 0 8 0.0 0.0 0 NA NA NA
2023 NA 3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2610707 AI NA NA NA NA NA 0.4021 0.2712 0.2670 0.3309 0.2808 0.1213 0.3523 0.3766 0.2116 0.0596 NA NA NA NA NA NA NA NA
2015 NA 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2610707 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 602 9 85.8 11.2 3 NA NA NA
2019 26182556 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 0 7 0.0 0.0 0 NA NA NA
2019 26188759 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA AI NA NA NA NA NA 0.2246 0.2246 0.2653 0.5101 0.2042 0.0204 0.4082 0.3673 0.2246 0.0000 51 NA NA NA NA NA NA NA
2019 26116120 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 0 10 0.0 0.0 0 NA NA NA
2023 26116880 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 1 100.0 0.0 0 NA NA NA
2019 26188600 3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA AI 4.9 0.9422 5.2393 202.28 187.82 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2019 26188724 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA AI NA NA NA NA NA 0.4855 0.2855 0.1715 0.3430 0.2856 0.2000 0.3144 0.4001 0.2283 0.0571 37 NA NA NA NA NA NA NA
2021 26116790 3 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 6 100.0 0.0 0 NA NA NA

Explicação

Muitas colunas da base não estão preenchidas de forma consistente em todos os arquivos. Cada planilha traz um conjunto diferente de informações, variando por ano e por etapa. Por isso, quando tudo é unificado, várias linhas ficam com NA simplesmente porque aquela informação não existia naquele ano ou naquele ciclo. Como os dados não podem ser misturados entre anos diferentes, essas linhas não podem ser descartadas em massa, senão iria perder registros válidos para aquele ano específico. Em resumo: os NAs aparecem porque as planilhas não têm o mesmo padrão de preenchimento ao longo do tempo.

3.5 Variáveis de interesse.

As variáveis utilizadas na análise foram selecionadas a partir do dicionário oficial presente nos arquivos do QEdu. Cada coluna do dataset consolidado mantém o significado original definido pelo Inep. Entre as variáveis de maior interesse estão:

  • inep_id — identificador único de cada escola, usado para garantir que as análises fossem feitas para as escolas corretas ao longo dos anos.

  • ideb — Índice de Desenvolvimento da Educação Básica, calculado pelo Inep a partir dos indicadores de fluxo escolar e do desempenho dos alunos, sendo o principal índice de qualidade educacional do país.

  • ano — ano de referência da observação, permitindo comparações temporais entre ciclos bianuais.

  • serie — etapa de ensino analisada (anos iniciais, anos finais ou ensino médio).

  • distorcao — percentual de alunos com dois ou mais anos de atraso na relação idade-série.

  • abandono — taxa de abandono escolar registrada para cada escola e ano.

  • aprovacao — taxa de aprovação dos estudantes.

Essas variáveis foram usadas por serem consistentes, sem problemas estruturais nos arquivos originais, e suficientes para realizar todos os cruzamentos e comparações descritos ao longo do relatório.

Separando apenas o identificador das escolas.

inep_ids <- dados_gerais %>%
  filter(!is.na(inep_id)) %>%
  distinct(inep_id) %>%
  arrange(inep_id)

inep_ids
## # A tibble: 82 × 1
##     inep_id
##       <int>
##  1 26115530
##  2 26115700
##  3 26115883
##  4 26115913
##  5 26115964
##  6 26115972
##  7 26115999
##  8 26116014
##  9 26116057
## 10 26116081
## # ℹ 72 more rows

4.1 Análise de aprendizado

Busquei analisar os resultados do municipio de 2015 a 2023 (dados registrados de 2 em 2 anos), sobre como se comportou, se a pandemia de alguma forma impactou e quais pontos apresentam piores indices.

colunas_interesse <- c(
  "lp_adequado",
  "mt_adequado",
  "lp_insuficiente",
  "lp_basico",
  "lp_proficiente",
  "lp_avancado",
  "mt_insuficiente",
  "mt_basico",
  "mt_proficiente",
  "mt_avancado"
)

dados_filtrados <- dados_gerais %>%
  filter(
    inep_id %in% inep_ids$inep_id,
    if_any(all_of(colunas_interesse), ~ !is.na(.))
  ) %>%
  select(inep_id, ano, all_of(colunas_interesse))

dados_filtrados
## # A tibble: 320 × 12
##     inep_id   ano lp_adequado mt_adequado lp_insuficiente lp_basico
##       <int> <int>       <dbl>       <dbl>           <dbl>     <dbl>
##  1 26115530  2015      0.161       0.035            0.496     0.343
##  2 26115530  2015      0.275       0.137            0.345     0.380
##  3 26115883  2015      0.348       0.140            0.148     0.504
##  4 26115913  2015      0.142       0.0383           0.273     0.585
##  5 26115964  2015      0.283       0.0459           0.272     0.444
##  6 26115972  2015      0.217       0.0408           0.140     0.643
##  7 26115999  2015      0.343       0.0917           0.172     0.485
##  8 26116057  2015      0.0801      0.0383           0.197     0.723
##  9 26116057  2015      0.185       0.106            0.489     0.327
## 10 26116081  2015      0.213       0.0989           0.356     0.432
## # ℹ 310 more rows
## # ℹ 6 more variables: lp_proficiente <dbl>, lp_avancado <dbl>,
## #   mt_insuficiente <dbl>, mt_basico <dbl>, mt_proficiente <dbl>,
## #   mt_avancado <dbl>
colunas_interesse <- c(
  "lp_adequado",
  "mt_adequado",
  "lp_insuficiente",
  "lp_basico",
  "lp_proficiente",
  "lp_avancado",
  "mt_insuficiente",
  "mt_basico",
  "mt_proficiente",
  "mt_avancado"
)

medias_ano_indicador <- dados_filtrados %>%
  select(ano, all_of(colunas_interesse)) %>%
  pivot_longer(
    cols = all_of(colunas_interesse),
    names_to = "indicador",
    values_to = "valor"
  ) %>%
  group_by(ano, indicador) %>%
  summarise(media = mean(valor, na.rm = TRUE), .groups = "drop") %>%
  arrange(ano, indicador)

medias_ano_indicador
## # A tibble: 40 × 3
##      ano indicador         media
##    <int> <chr>             <dbl>
##  1  2015 lp_adequado     0.247  
##  2  2015 lp_avancado     0.0350 
##  3  2015 lp_basico       0.499  
##  4  2015 lp_insuficiente 0.254  
##  5  2015 lp_proficiente  0.212  
##  6  2015 mt_adequado     0.0999 
##  7  2015 mt_avancado     0.00625
##  8  2015 mt_basico       0.495  
##  9  2015 mt_insuficiente 0.405  
## 10  2015 mt_proficiente  0.0936 
## # ℹ 30 more rows

4.1.1 Foco na Lingua portuguesa.

# Filtrar apenas indicadores de LP
lp_medias <- medias_ano_indicador %>%
  filter(indicador %in% c(
    "lp_adequado", "lp_insuficiente", "lp_basico",
    "lp_proficiente", "lp_avancado"
  ))

ggplot(lp_medias, aes(x = ano, y = media * 100, group = indicador, color = indicador)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  theme_minimal(base_size = 14) +
  labs(
    title = "Evolução do Aprendizado em Língua Portuguesa no Município",
    x = "Ano",
    y = "Percentual (%)",
    color = "Indicador"
  ) +
  scale_color_discrete(labels = c(
    "lp_adequado" = "Adequado",
    "lp_insuficiente" = "Insuficiente",
    "lp_basico" = "Básico",
    "lp_proficiente" = "Proficiente",
    "lp_avancado" = "Avançado"
  )) +
  scale_x_continuous(breaks = c(2015, 2017, 2019, 2023)) +
  scale_y_continuous(breaks = c(0,5,10,15,20,25,30,35,40,45,50)) +
  theme(
    plot.title = element_text(face = "bold", size = 16),
    legend.position = "right"
  )

Legenda:

Adequado: percentual de estudantes com aprendizagem considerada suficiente para a etapa. Representa domínio sólido dos conteúdos esperados.

Básico: percentual de estudantes que demonstram conhecimentos fundamentais, mas ainda abaixo do nível esperado. Indica aprendizado parcial e necessidade de reforço.

Insuficiente: percentual de estudantes com desempenho abaixo dos requisitos mínimos. Aponta dificuldades significativas na leitura, escrita e interpretação.

Proficiente: estudantes que demonstram domínio consistente das habilidades avaliadas, acima do nível básico. É um patamar de bom desempenho.

Avançado: estudantes que apresentam desempenho superior, demonstrando compreensão aprofundada e habilidades além do esperado para a etapa.

Conclusão

Houve uma redução consistente na proporção de alunos no nível básico, acompanhada por um aumento igualmente forte no nível adequado. O avanço no nível proficiente reforça a tendência de melhoria contínua do desempenho no município.

Os demais indicadores apresentaram variações pequenas ou pouco relevantes do ponto de vista interpretativo.

4.1.2 Foco em matemática.

# Filtrar apenas indicadores de MT
mt_medias <- medias_ano_indicador %>%
  filter(indicador %in% c(
    "mt_adequado", "mt_insuficiente", "mt_basico",
    "mt_proficiente", "mt_avancado"
  ))

ggplot(mt_medias, aes(x = ano, y = media * 100, group = indicador, color = indicador)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  theme_minimal(base_size = 14) +
  labs(
    title = "Evolução do Aprendizado em Matemática no Município",
    x = "Ano",
    y = "Percentual (%)",
    color = "Indicador"
  ) +
  scale_color_discrete(labels = c(
    "mt_adequado" = "Adequado",
    "mt_insuficiente" = "Insuficiente",
    "mt_basico" = "Básico",
    "mt_proficiente" = "Proficiente",
    "mt_avancado" = "Avançado"
  )) +
  scale_x_continuous(breaks = c(2015, 2017, 2019, 2023)) +
  scale_y_continuous(breaks = c(0,5,10,15,20,25,30,35,40,45,50)) +
  theme(
    plot.title = element_text(face = "bold", size = 16),
    legend.position = "right"
  )

Legenda:

Adequado: percentual de estudantes com aprendizagem considerada suficiente para a etapa. Representa domínio sólido dos conteúdos esperados.

Básico: percentual de estudantes que demonstram conhecimentos fundamentais, mas ainda abaixo do nível esperado. Indica aprendizado parcial e necessidade de reforço.

Insuficiente: percentual de estudantes com desempenho abaixo dos requisitos mínimos. Aponta dificuldades significativas na leitura, escrita e interpretação.

Proficiente: estudantes que demonstram domínio consistente das habilidades avaliadas, acima do nível básico. É um patamar de bom desempenho.

Avançado: estudantes que apresentam desempenho superior, demonstrando compreensão aprofundada e habilidades além do esperado para a etapa.

Conclusão

Observa-se uma oscilação contínua na proporção de alunos nos níveis insuficiente e básico, que, ainda assim, representam a maior parte dos estudantes abaixo do esperado para o ano. Por outro lado, os níveis adequado e proficiente mostraram crescimento ao longo do período, com um leve recuo no último ano da avaliação.

4.1.3 Comparativo entre Português e Matemática no municipio.

indicadores_comp <- c(
  "lp_basico", "lp_insuficiente",
  "mt_basico", "mt_insuficiente"
)

comparacao <- medias_ano_indicador %>%
  filter(indicador %in% indicadores_comp) %>%
  mutate(
    disciplina = ifelse(str_detect(indicador, "^lp_"), "Língua Portuguesa", "Matemática"),
    nivel = case_when(
      str_detect(indicador, "basico") ~ "Básico",
      str_detect(indicador, "insuficiente") ~ "Insuficiente"
    )
  )

ggplot(comparacao, aes(
  x = factor(ano),
  y = media * 100,   # já está em proporção, só converter pra porcentagem
  fill = nivel
)) +
  geom_col(position = "stack") +
  facet_wrap(~ disciplina, nrow = 1) +
  theme_minimal(base_size = 14) +
  labs(
    title = "Distribuição dos Níveis Básico e Insuficiente",
    subtitle = "Comparação entre Língua Portuguesa e Matemática",
    x = "Ano",
    y = "Percentual (%)",
    fill = "Nível"
  ) +
  scale_x_discrete(limits = c("2015","2017","2019","2023")) +
  scale_y_continuous(breaks = seq(0, 100, 10)) +
  scale_fill_manual(
    values = c(
      "Básico" = "#1f77b4",
      "Insuficiente" = "#d62728"
    )
  ) +
  theme(
    plot.title = element_text(face = "bold", size = 16),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.title.y = element_text(margin = margin(r = 10)),
    legend.position = "right"
  )

4.1.4 Conclusão

Os percentuais de aprendizado em matemática mostram uma leve melhora, mas ainda indicam resultados preocupantes na rede pública da cidade, com o pior desempenho em 2015, quando cerca de 90% dos estudantes apresentavam conhecimento insuficiente. Já o ensino de Língua Portuguesa apresenta desempenho um pouco melhor, mas ainda assim preocupante.

4.2 Análise da presença dos estudantes.

Nesta análise, examinarei o registro da presença dos estudantes ao longo dos anos, focando em sua permanência, conclusão do ano letivo e se estão na série adequada.

desistiram <- dados_gerais |>
  dplyr::filter(
    !is.na(matriculas),
    !is.na(abandonos)
  ) |>
  dplyr::select(
    inep_id,
    ano,
    matriculas,
    abandonos
  ) |>
  dplyr::distinct()

desistiram
## # A tibble: 1,140 × 4
##     inep_id   ano matriculas abandonos
##       <int> <int>      <int>     <dbl>
##  1 26115530  2015         14      14.3
##  2 26115530  2015         19       0  
##  3 26115530  2015         24      15  
##  4 26115530  2015         25       4.1
##  5 26115530  2015         35      18.1
##  6 26115530  2015        108       2  
##  7 26115530  2015        113      12.6
##  8 26115530  2015        110       5.7
##  9 26115530  2015         99       9.3
## 10 26115530  2015          0       0  
## # ℹ 1,130 more rows

4.2.1 Taxas de abandono.

pizza_abandono <- desistiram |>
  dplyr::mutate(
    abandonos_reais = matriculas * (abandonos / 100)
  ) |>
  dplyr::group_by(ano) |>
  dplyr::summarise(
    total_matriculas = sum(matriculas, na.rm = TRUE),
    total_abandonos = sum(abandonos_reais, na.rm = TRUE)
  ) |>
  dplyr::mutate(
    total_nao_abandonaram = total_matriculas - total_abandonos
  )
for (ano_atual in sort(unique(pizza_abandono$ano))) {
  
  df_ano <- pizza_abandono %>%
    filter(ano == ano_atual) %>%
    pivot_longer(
      cols = c(total_abandonos, total_nao_abandonaram),
      names_to = "tipo",
      values_to = "quantidade"
    ) %>%
    mutate(
      tipo = factor(tipo, levels = c("total_abandonos", "total_nao_abandonaram"),
                    labels = c("Estudantes que abandonaram", "Estudantes que continuaram")),
      pct = quantidade / sum(quantidade)        # para mostrar % na fatia
    )
  
  p <- ggplot(df_ano, aes(x = "", y = quantidade, fill = tipo)) +
    geom_col(width = 1, color = "white", show.legend = TRUE) +
    coord_polar(theta = "y") +
    geom_text(aes(label = paste0(round(pct*100, 1), "%")),
              position = position_stack(vjust = 0.5), size = 4) +
    scale_fill_manual(values = c("#c0392b", "#2ecc71")) +   # cores fixas (vermelho=abandono, verde=permanência)
    labs(
      title = paste("Distribuição de Abandono Escolar –", ano_atual),
      fill = "Situação dos Estudantes"
    ) +
    theme_void() +
    theme(
      plot.title = element_text(face = "bold", hjust = 0.5),
      legend.position = "right"
    )
  
  print(p)
}

Conclusão

Embora os dados de 2023 ainda não tenham sido divulgados, observa-se uma melhora contínua ao longo dos anos, com um leve recuo em 2021. A presença e a continuidade dos estudantes em sala de aula mostram-se consistentes, indicando que políticas públicas têm impacto positivo na permanência escolar.

4.2.2 Analise da distorção nos anos do fundamental anos iniciais (1º ao 5º ano) e anos finais (6º ao 9º ano).

A análise da distorção será realizada ano a ano apenas no ensino fundamental, uma vez que a oferta de ensino médio na rede pública de Paulista não está distribuída de forma abrangente por toda a cidade.

cols_distorcao <- paste0("ef_", 1:9, "ano")

dg_clean <- dados_gerais %>%
  mutate(across(all_of(cols_distorcao), ~na_if(trimws(.), ""))) %>%  # "" vira NA
  mutate(across(all_of(cols_distorcao), ~as.numeric(str_replace(., ",", "."))))

distoados <- dg_clean %>%
  filter(ano >= 2015) %>%                                  
  select(ano, all_of(cols_distorcao)) %>%
  pivot_longer(cols = starts_with("ef_"),
               names_to = "serie",
               values_to = "distorcao") %>%
  filter(!is.na(distorcao)) %>%                             
  mutate(
    serie = as.numeric(str_extract(serie, "\\d+"))           
  ) %>%
  group_by(ano, serie) %>%
  summarise(distorcao = mean(distorcao, na.rm = TRUE),
            .groups = "drop") %>%
  arrange(ano, serie)

4.2.2.1 Distorção generalizada por ano do fundamental.

for (s in sort(unique(distoados$serie))) {
  
  temp <- distoados %>% filter(serie == s)
  
  p <- ggplot(temp, aes(x = ano, y = distorcao)) +
    geom_col(fill = "#2c3e50") +
    geom_text(aes(label = round(distorcao,1)), vjust = -0.5) +
    labs(
      title = paste0("Distorção Idade-Série – ", s, "º Ano"),
      x = "Ano Letivo",
      y = "Percentual (%)"
    ) +
    scale_x_continuous(breaks = c(2015, 2017, 2019, 2021, 2023))
    theme_minimal(base_size = 10)
  
  print(p)
}

Conclusão

Durante os anos da pandemia de COVID-19, os anos finais do ensino fundamental (6º ao 9º ano) registraram piora expressiva nos resultados, com aumento significativo nos números, e, mesmo após o término da pandemia, os percentuais ainda não retornaram aos níveis anteriores. Já os anos iniciais (1º ao 5º ano) apresentaram flutuações nos percentuais, mas sem variações tão expressivas.

4.2.2.2 Analise comparando o desempenho dos anos.

ggplot(distoados, aes(x = ano, y = distorcao, color = factor(serie))) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  labs(
    title = "Evolução da Distorção Idade-Série (1º ao 9º ano)",
    x = "Ano Letivo",
    y = "Percentual (%)",
    color = "Ano"
  ) +
  scale_x_continuous(breaks = c(2015, 2017, 2019, 2021, 2023)) +
  scale_y_continuous(breaks = c(1,5,10,15,20,25,30,35)) +
  theme_minimal(base_size = 14)

Conclusão

Alguns anos específicos, como observado nos gráficos individualizados, apresentaram pioras muito expressivas no quesito de distorção, destacando-se significativamente em relação aos demais anos.

4.2.2.3 Analise geral da distorção ano a ano no municipio.

# anos fixos que você sempre quer ver
anos_desejados <- c(2015, 2017, 2019, 2021)

# --- 1) preparar matriculas por ano/serie (a partir de dados_gerais) ---
matriculas_ano_serie <- dados_gerais %>%
  # garantir tipos / limpar strings vazias
  mutate(
    serie_id = as.character(serie_id) |> trimws(),
    matriculas = as.numeric(str_replace(as.character(matriculas), ",", ".")),
    ano = as.numeric(as.character(ano))
  ) %>%
  filter(!is.na(serie_id), !is.na(matriculas), !is.na(ano)) %>%
  mutate(serie = as.integer(str_extract(serie_id, "\\d+"))) %>%
  filter(!is.na(serie)) %>%
  group_by(ano, serie) %>%
  summarise(total_matriculas = sum(matriculas, na.rm = TRUE), .groups = "drop") %>%
  filter(ano %in% anos_desejados)

if (nrow(matriculas_ano_serie) == 0) {
  matriculas_ano_serie <- dados_gerais %>%
    mutate(
      matriculas = as.numeric(str_replace(as.character(matriculas), ",", ".")),
      ano = as.numeric(as.character(ano))
    ) %>%
    filter(!is.na(matriculas), !is.na(ano)) %>%
    group_by(ano) %>%
    summarise(total_matriculas = sum(matriculas, na.rm = TRUE), .groups = "drop") %>%
    filter(ano %in% anos_desejados) %>%
    mutate(serie = NA_integer_)
}

# --- 2) preparar distoados (garantir tipos, filtrar anos desejados) ---
distoados_clean <- distoados %>%
  mutate(
    ano = as.numeric(as.character(ano)),
    serie = as.integer(serie),
    distorcao = as.numeric(distorcao)   # percent (ex: 12.5)
  ) %>%
  filter(ano %in% anos_desejados)

joined <- distoados_clean %>%
  left_join(matriculas_ano_serie, by = c("ano", "serie"))

matriculas_por_ano <- matriculas_ano_serie %>%
  group_by(ano) %>%
  summarise(total_matriculas_ano = sum(total_matriculas, na.rm = TRUE), .groups = "drop")

joined <- joined %>%
  left_join(matriculas_por_ano, by = "ano") %>%
  mutate(
    matriculas_usadas = if_else(!is.na(total_matriculas), total_matriculas, total_matriculas_ano)
  )

if (all(is.na(joined$matriculas_usadas))) {
  warning("Nenhuma contagem de matriculas por serie/ano encontrada. Resultado usará média simples das distorções por ano (não ponderada).")
  resumo_ano <- joined %>%
    group_by(ano) %>%
    summarise(
      distorcao_percent = mean(distorcao, na.rm = TRUE),
      total_matriculas = NA_real_,
      metodo = "media_simples",
      .groups = "drop"
    )
} else {
  # calcula abandonos reais = distorcao(%) /100 * matriculas_usadas
  resumo_ano <- joined %>%
    filter(!is.na(distorcao)) %>%
    mutate(abandonos_reais = (distorcao / 100) * matriculas_usadas) %>%
    group_by(ano) %>%
    summarise(
      total_abandonos = sum(abandonos_reais, na.rm = TRUE),
      total_matriculas = sum(matriculas_usadas, na.rm = TRUE),
      .groups = "drop"
    ) %>%
    mutate(
      distorcao_percent = if_else(total_matriculas > 0,
                                  (total_abandonos / total_matriculas) * 100,
                                  NA_real_),
      metodo = "ponderada"
    )
}
# Garante a ordem dos anos (sempre mostrar 2015..2023)
resumo_ano <- resumo_ano %>%
  filter(ano %in% anos_desejados) %>%
  mutate(ano = factor(ano, levels = anos_desejados))

ggplot(resumo_ano, aes(x = ano, y = distorcao_percent)) +
  geom_col(fill = "#2c3e50", width = 0.6) +
  geom_text(aes(label = ifelse(is.na(distorcao_percent), "NA", paste0(round(distorcao_percent,1), "%"))),
            vjust = -0.5, size = 4) +
  scale_y_continuous(limits = c(0, 50), expand = expansion(mult = c(0, 0.05))) +
  labs(
    title = "Distorção (percentual ponderado) por Ano Letivo",
    x = "Ano",
    y = "Distorção (%)"
  ) +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(face = "bold")) +
  scale_x_discrete(drop = FALSE)

**Conclusão*

Observando o panorama geral das distorções ao longo dos anos letivos, fica evidente que a pandemia provocou piora nos índices. Como os dados de matrícula de 2023 ainda não foram divulgados, não foi possível calcular a porcentagem de alunos em distorção para esse ano, mas os dados individuais dos anos anteriores indicam tendência de piora nesse indicador.

4.3 Melhor, pior e média do município em lingua portuguesa e matemática.

Nessa sessão irei buscar pelas melhores e piores escolas considerando indices positivos de aprendizado em lingua portuguesa e matemática e as menores taxas de distorção.

anos_validos <- c(2015, 2017, 2019, 2021, 2023)

# LIMPEZA E PREPARAÇÃO
dados_clean <- dados_gerais %>%
  mutate(
    inep_id = as.character(inep_id),
    ano = as.numeric(ano)
  ) %>%
  filter(
    !is.na(inep_id),
    !is.na(ano),
    ano %in% anos_validos,
    ciclo_id %in% c("AI", "AF")
  ) %>%
  filter(!is.na(nota_mt), !is.na(nota_lp)) %>%
  mutate(
    nota_mt = as.numeric(nota_mt),
    nota_lp = as.numeric(nota_lp)
  ) %>%
  group_by(inep_id, ano) %>%
  summarise(
    nota_mt = mean(nota_mt, na.rm = TRUE),
    nota_lp = mean(nota_lp, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(Score = (nota_mt + nota_lp) / 2)

# GERA TABELA FINAL
final_list <- lapply(anos_validos, function(a) {
  ano_df <- dados_clean %>% filter(ano == a)

  media_ano <- mean(ano_df$Score, na.rm = TRUE)

  melhor <- ano_df %>% arrange(desc(Score)) %>% slice(1) %>% mutate(tipo = "MELHOR")
  pior   <- ano_df %>% arrange(Score) %>% slice(1) %>% mutate(tipo = "PIOR")

  linha_media <- tibble(
    tipo = "MEDIA_ANO",
    inep_id = paste0("MEDIA_", a),
    ano = a,
    nota_mt = NA_real_,
    nota_lp = NA_real_,
    Score = media_ano
  )

  bind_rows(linha_media, melhor, pior)
})

tabela_final <- bind_rows(final_list)

tabela_final
## # A tibble: 15 × 6
##    tipo      inep_id      ano nota_mt nota_lp Score
##    <chr>     <chr>      <dbl>   <dbl>   <dbl> <dbl>
##  1 MEDIA_ANO MEDIA_2015  2015     NA      NA   190.
##  2 MELHOR    26136549    2015    218.    212.  215.
##  3 PIOR      26116235    2015    173.    159.  166.
##  4 MEDIA_ANO MEDIA_2017  2017     NA      NA   203.
##  5 MELHOR    26116251    2017    228.    233.  230.
##  6 PIOR      26116820    2017    175.    169.  172.
##  7 MEDIA_ANO MEDIA_2019  2019     NA      NA   206.
##  8 MELHOR    26116804    2019    255.    247.  251.
##  9 PIOR      26188759    2019    187.    176.  181.
## 10 MEDIA_ANO MEDIA_2021  2021     NA      NA   201.
## 11 MELHOR    26116804    2021    251.    258.  254.
## 12 PIOR      26116766    2021    182.    170.  176.
## 13 MEDIA_ANO MEDIA_2023  2023     NA      NA   206.
## 14 MELHOR    26116804    2023    259.    261.  260.
## 15 PIOR      26188589    2023    182.    168.  175.
tabela_escolas <- tibble(
  inep_id = c("26116804", "26188589", "26116766", "26188759","26116251","26136549","26116235","26116820"),
  nome_escola = c("
ESCOLA MUNICIPAL DRA GELDA AMORIM", "ESCOLA MUNICIPAL PROFESSORA IRACEMA CASTRO", "
ESCOLA MUNICIPAL ABELARDO SALES DE SIQUEIRA","
ESCOLA MUNICIPAL PROFESSORA EDNA MARINHO DA SILVA", "
ESCOLA MUNICIPAL JOAO F DE ALBUQUERQUE","
ESCOLA MUL PROF MARIA CONCEICAO DA PAZ","
ESCOLA MUNICIPAL ZULIMA PINHO ALVES","
ESCOLA MUNICIPAL HEINZ HERING")
)

anos_validos <- c(2015, 2017, 2019, 2021, 2023)

# tabela_final: já criada antes
# tabela_escolas: tabela com inep_id e nome_escola

tabela_final_nomes <- tabela_final %>%
  mutate(inep_id = as.character(inep_id)) %>%
  left_join(tabela_escolas, by = "inep_id") %>% 
  mutate(
    tipo = factor(tipo, levels = c("MEDIA_ANO", "MELHOR", "PIOR")),
    nome_plot = ifelse(tipo == "MEDIA_ANO",
                       paste0("Média ", ano),
                       nome_escola)
  )

for (a in anos_validos) {
  
  df_plot <- tabela_final_nomes %>% filter(ano == a)

  print(
    ggplot(df_plot, aes(x = tipo, y = Score, fill = tipo)) +
      geom_col() +
      geom_text(
        aes(label = paste0(nome_plot, "\n", round(Score, 2))),
        vjust = 3,
        size = 3
      ) +
      labs(
        title = paste("Ano", a, "- Média, Melhor e Pior Escola"),
        x = "",
        y = "Score"
      ) +
      theme_minimal(base_size = 12) +
      theme(legend.position = "none")
  )
}

Conclusão

Ao analisar os dados, fica claro que o desempenho bruto das escolas em Língua Portuguesa e Matemática não explica sozinho o nível de “aprendizado” nem o resultado final do IDEB. As notas disponibilizadas nas planilhas representam valores absolutos, enquanto o indicador “aprendizado” utiliza notas padronizadas, que passam por transformação estatística antes de gerar o valor final.

Por isso, é comum observar casos em que uma escola apresenta médias superiores em LP e MT, mas não alcança os maiores índices de aprendizado. Além disso, o IDEB depende também do fluxo escolar — aprovação, reprovação e abandono — o que faz com que escolas com desempenho intermediário possam superar outras com notas mais altas, desde que apresentem fluxo muito eficiente.

Em resumo: melhores notas não garantem melhor aprendizado, e melhor aprendizado não garante o melhor IDEB, pois cada indicador responde a componentes diferentes e não lineares do processo educacional.

4.4 Previsão

# Calcular média de IDEB por ano, ignorando NAs
ideb_ano <- dados_gerais %>%
  group_by(ano) %>%
  summarise(ideb = mean(ideb, na.rm = TRUE)) %>%
  ungroup() %>%
  filter(!is.na(ideb))  # Remove anos que ficaram NA após a média

# Previsão para 2025 com base nos anos válidos
ideb_media <- mean(ideb_ano$ideb, na.rm = TRUE)
ideb_previsto_2025 <- data.frame(
  ano = 2025,
  ideb = ideb_media
)

# Combinar dados históricos e previsão
dados_plot <- bind_rows(ideb_ano, ideb_previsto_2025) %>%
  mutate(tipo = ifelse(ano == 2025, "Previsão", "Histórico"))

# Plot com linha de tendência
ggplot(dados_plot, aes(x = factor(ano), y = ideb, group = 1)) +
  geom_col(aes(fill = tipo), width = 0.5) +
  geom_text(aes(label = round(ideb,1)), vjust = -0.5) +
  geom_line(data = filter(dados_plot, tipo == "Histórico"), aes(y = ideb), 
            color = "#2980b9", size = 1, linetype = "dashed") +
  geom_point(aes(color = tipo), size = 3) +
  scale_fill_manual(values = c("Histórico" = "#2c3e50", "Previsão" = "#e74c3c")) +
  scale_color_manual(values = c("Histórico" = "#2c3e50", "Previsão" = "#e74c3c")) +
  scale_y_continuous(limits = c(0, 8), expand = expansion(mult = c(0, 0.05))) 

  labs(
    title = "IDEB: Histórico e previsão para 2025",
    x = "Ano",
    y = "IDEB",
    fill = "",
    color = ""
  ) +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(face = "bold"))
## NULL

Conclusão

Mesmo considerando a previsão matemática, o município continua distante das metas ideais do IDEB, com resultados muito abaixo da média do estado (5,7 nos anos iniciais e 5,0 nos anos finais) e da média nacional (6,0 nos anos iniciais e 5,0 nos anos finais). Isso evidencia a necessidade de investimentos e estudos aprofundados voltados à melhoria da qualidade da educação na rede municipal.

5.1 Declaração do problema

O problema abordado neste projeto é a baixa qualidade do aprendizado dos estudantes da rede pública de Paulista, evidenciada por altos índices de distorção idade-série e pelo baixo desempenho em Língua Portuguesa e Matemática. A investigação busca compreender a evolução desses indicadores ao longo dos anos, identificar os impactos da pandemia e destacar escolas com melhores e piores resultados, fornecendo subsídios para políticas públicas que melhorem a aprendizagem e a permanência dos alunos na escola.

5.2 Abordagem do problema

A declaração do problema foi abordada por meio da análise de dados educacionais da rede pública de Paulista, abrangendo os anos letivos de 2015 a 2023. Foram utilizados indicadores de aprendizado em Língua Portuguesa e Matemática, taxas de distorção idade-série e registros de presença dos alunos. A metodologia empregada envolveu o tratamento e organização dos dados no R, cálculo de médias e percentuais por ano e escola, além da visualização dos resultados por meio de gráficos de barras, linhas e comparativos, permitindo identificar tendências, oscilações e as melhores e piores escolas em cada indicador.

5.3 Conclusão dos insights

A análise revelou que, embora alguns indicadores de aprendizado apresentem leve melhora ao longo dos anos, a maioria dos estudantes ainda se encontra nos níveis insuficiente e básico, especialmente em Matemática. Os anos finais do ensino fundamental (6º ao 9º) foram mais afetados durante a pandemia, com piora significativa na distorção idade-série e no desempenho escolar, sendo poucos os dados que apresentaram melhora expressiva após esse período. Observou-se também que nem sempre as escolas com melhores notas individuais registram um IDEB mais alto, indicando que o desempenho médio não reflete completamente a qualidade de aprendizagem ou a progressão de todos os alunos. Além disso, a comparação entre escolas permitiu identificar unidades com melhores resultados e menor distorção, reforçando a importância de políticas públicas que favoreçam a permanência e o aprendizado dos estudantes.

5.4 Implicações para os potenciais beneficiados

As implicações desta análise para gestores e formuladores de políticas educacionais incluem a identificação de escolas que necessitam de atenção prioritária, bem como práticas que podem ser replicadas nas unidades com melhores resultados. Os dados permitem monitorar a evolução do aprendizado e da distorção idade-série ao longo do tempo, ajudando a direcionar recursos e estratégias pedagógicas de forma mais eficiente. Além disso, evidenciam que altos índices de desempenho em avaliações isoladas não garantem necessariamente um IDEB elevado, reforçando a necessidade de abordagens integradas que considerem tanto a aprendizagem quanto a permanência dos alunos na escola.

5.5 Limitações dos dados

A análise apresenta algumas limitações. Embora o foco no ensino fundamental tenha sido proposital, já que a rede municipal de Paulista oferece praticamente apenas esse nível de ensino, os dados de 2023 ainda não estavam disponíveis por completo, o que impede avaliar completamente a evolução mais recente. Além disso, os indicadores utilizados não capturam aspectos qualitativos do aprendizado, como engajamento ou metodologia pedagógica.

Para aprimorar ou expandir a análise, seria interessante incluir dados futuros assim que disponíveis, incorporar variáveis socioeconômicas, qualitativas e verba de cada escola, e utilizar modelos estatísticos ou de aprendizado de máquina para prever tendências e identificar fatores que mais impactam o desempenho e a permanência dos alunos.

Além disso, a maioria dos modelos testados não encontrou padrões ou relações significativas nos dados disponíveis, indicando que os indicadores atuais podem ser insuficientes para capturar todos os fatores que influenciam o desempenho e a permanência dos alunos.