library(tidyverse)
## Warning: pacote 'purrr' foi compilado no R versão 4.5.2
## Warning: pacote 'dplyr' foi compilado no R versão 4.5.2
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.1 ✔ stringr 1.5.2
## ✔ ggplot2 4.0.0 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.2.0
## ── 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
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) %>%
mutate(across(everything(), ~ type.convert(., as.is = TRUE)))
glimpse(dados_gerais)
## Rows: 45,957
## Columns: 46
## $ Variável <chr> "ibge_id", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ Descrição <chr> "Código IBGE da unidade da federação e municípios", NA…
## $ Códigos <chr> "7-Brasil", "11-RO", "12-AC", "13-AM", "14-RR", "15-PA…
## $ ano <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ inep_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ dependencia_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ localizacao_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_1ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_2ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_3ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_4ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_5ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_6ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_7ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_8ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_9ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_total_ai <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_total_af <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ef_total <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ em_1ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ em_2ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ em_3ano <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ em_4ano <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ em_total <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ibge_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ciclo_id <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ideb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ fluxo <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ aprendizado <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nota_mt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nota_lp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ lp_adequado <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mt_adequado <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ lp_insuficiente <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ lp_basico <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ lp_proficiente <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ lp_avancado <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mt_insuficiente <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mt_basico <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mt_proficiente <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mt_avancado <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ matriculas <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ serie_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ aprovados <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ reprovados <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ abandonos <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
inep_ids <- dados_gerais %>%
filter(!is.na(inep_id)) %>%
distinct(inep_id) %>%
arrange(inep_id)
inep_ids
## # A tibble: 203 × 1
## inep_id
## <int>
## 1 26115441
## 2 26115450
## 3 26115476
## 4 26115530
## 5 26115557
## 6 26115654
## 7 26115662
## 8 26115700
## 9 26115808
## 10 26115824
## # ℹ 193 more rows
Busquei analisar os resultados do municipio de 2015 em diante (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: 960 × 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
## # ℹ 950 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
# 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_x_continuous(breaks = c(2015, 2017, 2019, 2021, 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"
)
# 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_x_continuous(breaks = c(2015, 2017, 2019, 2021, 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"
)
desistiram <- dados_gerais |>
dplyr::filter(
!is.na(matriculas),
!is.na(abandonos)
) |>
dplyr::select(
inep_id,
ano,
matriculas,
abandonos
) |>
dplyr::distinct()
desistiram
## # A tibble: 3,850 × 4
## inep_id ano matriculas abandonos
## <int> <int> <int> <dbl>
## 1 26115441 2015 119 0
## 2 26115441 2015 195 0
## 3 26115441 2015 164 0
## 4 26115450 2015 33 0
## 5 26115450 2015 51 0
## 6 26115450 2015 39 0
## 7 26115450 2015 54 0
## 8 26115450 2015 30 0
## 9 26115450 2015 41 0
## 10 26115450 2015 24 0
## # ℹ 3,840 more rows
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
)
library(ggplot2)
for (ano_atual in unique(pizza_abandono$ano)) {
df_ano <- pizza_abandono |>
dplyr::filter(ano == ano_atual) |>
tidyr::pivot_longer(
cols = c(total_abandonos, total_nao_abandonaram),
names_to = "tipo",
values_to = "quantidade"
)
print(
ggplot(df_ano, aes(x = "", y = quantidade, fill = tipo)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
labs(
title = paste("Distribuição de Abandono Escolar –", ano_atual),
fill = "Situação"
) +
theme_void()
)
}
Analisando como a distorção se comportou em cada ano letivo e nivel de ensino (Distorção se trata de estudantes que estão abaixo série ideal para a idade do mesmo)
library(tidyverse)
# colunas
cols_distorcao <- paste0("ef_", 1:9, "ano")
# limpar e converter valores
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(., ",", "."))))
# gerar tabela final
distoados <- dg_clean %>%
filter(ano >= 2015) %>% # anos válidos
select(ano, all_of(cols_distorcao)) %>%
pivot_longer(cols = starts_with("ef_"),
names_to = "serie",
values_to = "distorcao") %>%
filter(!is.na(distorcao)) %>% # só o que existe
mutate(
serie = as.numeric(str_extract(serie, "\\d+")) # extrai número da série
) %>%
group_by(ano, serie) %>%
summarise(distorcao = mean(distorcao, na.rm = TRUE),
.groups = "drop") %>%
arrange(ano, serie)
library(ggplot2)
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)
}
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 = "Série"
) +
scale_x_continuous(breaks = c(2015, 2017, 2019, 2021, 2023)) +
scale_y_continuous(breaks = c(1,26)) +
theme_minimal(base_size = 14)
library(tidyverse)
# 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"
)
}
library(ggplot2)
# 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, 20), 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)
Dados apontam que quanto maior o nivel de ensino, maiores são os problemas em manter o estudante de acordo com as taxas ideais, tanto no sentido de abandono, distorção e desempenho, mostrando também que após o periodo de pandemia/troca de gestão no municipio, os dados tiveram uma tendência a piorar.