Este documento apresenta uma análise exploratória de dados e discussões acerca do acesso de estudantes de escolas públicas do Ceará à internet em suas respectivas instituições de ensino. Este trabalho é um requisito para aprovação na disciplina de Fundamentos de Estatística da Universidade de Fortaleza, no âmbito do curso de Inteligência Artificial.
Autor: Pedro Florencio de Almeida Neto | Cientista de Dados
Objetivo Geral:
Objetivos Específicos:
# install.packages("readxl")
# install.packages("leaflet")
# install.packages("echarts4r")
# install.packages("BAMMtools")
library(sf)
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(readxl)
library(scales)
library(leaflet)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ readr 2.1.5
## ✔ ggplot2 3.5.2 ✔ stringr 1.5.1
## ✔ lubridate 1.9.4 ✔ tibble 3.3.0
## ✔ purrr 1.1.0 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ readr::col_factor() masks scales::col_factor()
## ✖ purrr::discard() masks scales::discard()
## ✖ 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
library(echarts4r)
library(BAMMtools)
## Loading required package: ape
##
## Attaching package: 'ape'
##
## The following object is masked from 'package:dplyr':
##
## where
library(RColorBrewer)
Os dados foram baixados do Diagnóstico da
Conectividade na Educação (SIMET) e são oriundos do Censo Escolar
2024 (INEP). O script 01-filtra-base-ceara.R é responsável
por filtrar os dados brutos para o estado do Ceará e salvar no diretório
processed_data.
df <- read_excel('data/processed-data/base_ceara_validada.xlsx')
df <- df[!is.na(df$escolar_co_municipio), ]
head(df)
## # A tibble: 6 × 59
## escolar_co_entidade escolar_nu_ano_censo escolar_no_entidade
## <dbl> <dbl> <chr>
## 1 23000465 2024 JOAO LOURENCO PEREIRA ROCHA EEIEF
## 2 23000660 2024 MARIA NAZARE VIANA EEIEF
## 3 23000708 2024 HIGINO DE SOUZA BRANDAO EEIEF
## 4 23001119 2024 RAIMUNDO ROSA DO NASCIMENTO EEIEF
## 5 23003014 2024 MURILO ROCHA AGUIAR EEF DEP
## 6 23003359 2024 ANTONIO TEIXEIRA DE FRANCA EEF
## # ℹ 56 more variables: escolar_tp_situacao_funcionamento <chr>,
## # escolar_co_uf <dbl>, escolar_co_municipio <dbl>, escolar_co_distrito <dbl>,
## # escolar_tp_dependencia <chr>, escolar_tp_localizacao <chr>,
## # escolar_qt_desktop_aluno <dbl>, escolar_qt_comp_portatil_aluno <dbl>,
## # escolar_qt_tablet_aluno <dbl>, escolar_in_laboratorio_informatica <chr>,
## # escolar_in_internet <chr>, escolar_in_internet_alunos <chr>,
## # escolar_in_internet_aprendizagem <chr>, escolar_tp_rede_local <chr>, …
gdf_ceara <- st_read('data/processed-data/limites_ceara.geojson')
## Reading layer `limites_ceara' from data source
## `/Users/pedroflorencio/Documents/conecta-ceara/data/processed-data/limites_ceara.geojson'
## using driver `GeoJSON'
## Simple feature collection with 184 features and 6 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -41.42352 ymin: -7.858182 xmax: -37.25329 ymax: -2.784323
## Geodetic CRS: WGS 84
# remocao das 28 ultimas colunas
df <- df[, 1:(ncol(df) - 28)]
# remocao de colunas especificas
cols_to_remove <- c('escolar_nu_ano_censo',
'escolar_co_uf',
'escolar_co_distrito',
'comparador_empresas',
'satelite_mec',
'recurso_recebido')
df <- df[, !(names(df) %in% cols_to_remove)]
knitr::kable(data.frame('Faltantes' = colSums(is.na(df))))
| Faltantes | |
|---|---|
| escolar_co_entidade | 0 |
| escolar_no_entidade | 0 |
| escolar_tp_situacao_funcionamento | 0 |
| escolar_co_municipio | 0 |
| escolar_tp_dependencia | 0 |
| escolar_tp_localizacao | 0 |
| escolar_qt_desktop_aluno | 0 |
| escolar_qt_comp_portatil_aluno | 0 |
| escolar_qt_tablet_aluno | 0 |
| escolar_in_laboratorio_informatica | 0 |
| escolar_in_internet | 0 |
| escolar_in_internet_alunos | 0 |
| escolar_in_internet_aprendizagem | 0 |
| escolar_tp_rede_local | 0 |
| escolar_energia | 0 |
| escolar_qtematriculas | 0 |
| escolar_qtematriculas_maior_turno | 12 |
| escolar_num_turmas | 39 |
| latitude | 0 |
| longitude | 0 |
| nm_regiao | 0 |
| nm_estado | 0 |
| nm_municipio | 0 |
| porte_escola | 0 |
| escolar_tipo_tecnologia | 6 |
df %>%
count(escolar_tipo_tecnologia, name='contagem', sort=TRUE)
## # A tibble: 7 × 2
## escolar_tipo_tecnologia contagem
## <chr> <int>
## 1 ADSL 1756
## 2 sem informação 1706
## 3 Satélite 1330
## 4 Fibra 669
## 5 Rede Celular 477
## 6 Rádio 27
## 7 <NA> 6
Para a variável escolar_tipo_tecnologia optou-se por
preencher NA com o termo sem informação, conforme
string contida nesta coluna.
df$escolar_tipo_tecnologia <- df$escolar_tipo_tecnologia %>% replace_na('sem informação')
df$escolar_co_municipio <- as.character(df$escolar_co_municipio)
# verificando se as colunas booleanas possuem mais formas de escrita de 'Sim'e 'Nao'
cols_booleanas <- c('escolar_in_laboratorio_informatica',
'escolar_in_internet',
'escolar_in_internet_alunos',
'escolar_in_internet_aprendizagem')
lapply(df[cols_booleanas], unique)
## $escolar_in_laboratorio_informatica
## [1] "Nao" "Sim"
##
## $escolar_in_internet
## [1] "Sim" "Nao"
##
## $escolar_in_internet_alunos
## [1] "Nao" "Sim"
##
## $escolar_in_internet_aprendizagem
## [1] "Sim" "Nao"
As colunas booleanas não apresentam valores distintos de
Sim e Nao. Portanto, é seguro realizar a troca
para valores binários considerando apenas estas duas
strings.
# substituindo colunas de 'Sim' e 'Nao' por variavel booleana
df <- df %>%
mutate(across(all_of(cols_booleanas),
~ifelse(. == "Sim", 1, 0)))
# selecao das colunas necessarias
cols <- c("escolar_co_entidade", "escolar_no_entidade", "escolar_tp_dependencia")
df_dependencias <- df %>% select(all_of(cols))
# valores absolutos
df_freq <- as.data.frame(table(df_dependencias$escolar_tp_dependencia))
colnames(df_freq) <- c("TP_DEPENDENCIA","QUANTIDADE")
# percentual
df_freq$PERCENTUAL <- round(df_freq$QUANTIDADE/sum(df_freq$QUANTIDADE), 2)
# visualizacao
df_freq %>%
e_charts(TP_DEPENDENCIA) %>%
e_pie(
QUANTIDADE,
radius = c("45%", "75%"),
label = list(
show = TRUE,
position = "outside",
formatter = "{d}%",
fontSize = 12,
color = "black"
)
) %>%
e_legend(right = "25%") %>%
e_title(
text = "Gráfico 01: Dependência Administrativa das Escolas Públicas do Ceará",
textStyle = list(
color = "black",
fontSize = 14
)) %>%
e_theme("macarons")
Observa-se uma predominância da quantidade de escolas municipais, isto é, de educação básica no estado do Ceará. Pode-se ressaltar que o número total de instituições não reflete necessariamente um alta taxa de escolarização, necessitando portanto de uma análise do número de matriculados em cada dependência administrativa no Estado.
# colunas necessarias
cols_loc <- c('escolar_co_entidade',
'escolar_co_entidade',
'nm_municipio',
'escolar_tp_localizacao')
df_localizacao <- df %>% select(all_of(cols_loc))
head(df_localizacao)
## # A tibble: 6 × 3
## escolar_co_entidade nm_municipio escolar_tp_localizacao
## <dbl> <chr> <chr>
## 1 23000465 ACARAÚ Rural
## 2 23000660 ACARAÚ Rural
## 3 23000708 ACARAÚ Urbana
## 4 23001119 ACARAÚ Rural
## 5 23003014 CAMOCIM Urbana
## 6 23003359 CAMOCIM Rural
# valores absolutos
df_freq_loc <- as.data.frame(table(df_localizacao$escolar_tp_localizacao))
colnames(df_freq_loc) <- c("TP_LOCALIZACAO","QUANTIDADE")
df_freq_loc
## TP_LOCALIZACAO QUANTIDADE
## 1 Rural 2509
## 2 Urbana 3462
df_freq_loc %>%
e_charts(TP_LOCALIZACAO) %>%
e_bar(QUANTIDADE, name = "") %>%
e_labels(show = TRUE) %>%
e_title(text='Gráfico 02: Localização das Escolas Cearenses',
textStyle = list(color = "black", fontSize = 14)) %>%
e_theme('macarons')
Há uma predominância de escolas em zona urbana, embora, a quantidade de instituições em zonas rurais apresenta-se com um valor relevante.
# agrupando por municipio e somando a quantidade de laboratorios de informatica
df_filtered_lab <- df %>%
group_by(escolar_co_municipio) %>%
summarise(
quantidade_escolas_laboratorios = sum(escolar_in_laboratorio_informatica),
quantidade_escolas = n())
Adicionando coluna com os valores relativos de escolas que contêm laboratórios de informática
df_filtered_lab <- mutate(df_filtered_lab,
percentual_laboratorio = quantidade_escolas_laboratorios / quantidade_escolas)
Adicionando a coluna geometry no dataframe df_filtered
df_join_lab <- gdf_ceara %>%
left_join(df_filtered_lab, by = c("codigo_ibge"="escolar_co_municipio"))
dim(df_join_lab)
## [1] 184 10
Mapa Coroplético do Percentual de Laboratórios nas Cearenses
A definição de quantidade de categorias seguiu-se a regra de Freedman-Diaconis1, em que:
\[ w = 2*IQR*n^{-\frac{1}{3}} \]
\[ k = \frac{max-min}{w} \]
Onde:
IQR: amplitude interquartil
n: número de observações
k: quantidade de categorias (bins)
Para escolha dos valores que limitam cada categoria, adotou-se o método Jenks-Caspall.
Q1 <- quantile(df_join_lab$percentual_laboratorio, probs = 0.25)
Q2 <- quantile(df_join_lab$percentual_laboratorio, probs = 0.50)
Q3 <- quantile(df_join_lab$percentual_laboratorio, probs = 0.75)
IQR <- (Q3-Q1)
IQR
## 75%
## 0.1794872
n = nrow(df_join_lab)
n
## [1] 184
w = 2*IQR*(n**(-1/3))
w
## 75%
## 0.06311377
min = min(df_join_lab$percentual_laboratorio)
max = max(df_join_lab$percentual_laboratorio)
k = (max - min)/w
k
## 75%
## 15.01049
15 classes são recomendadas pelo cálculo do método, entretanto, por motivos de visualização e produção de um relatório em linguagem simples, optou-se por 5 categorias.
Visualização do mapa
# bins <- categories
bins <- 5 # Natural Breaks (Intervalos iguais)
pal <- colorRampPalette(brewer.pal(9, "YlOrRd"))(15)
pal_fun <- colorBin(
palette = pal,
domain = df_join_lab$percentual_laboratorio,
bins = 5,
na.color = "transparent"
)
labels <- sprintf(
"<strong>%s</strong><br/>%.1f%%",
df_join_lab$municipio, df_join_lab$percentual_laboratorio*100
) %>% lapply(htmltools::HTML)
m <- leaflet(df_join_lab) %>%
setView(lng = -39.5, lat = -5.2, zoom = 6) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(
fillColor = ~pal_fun(percentual_laboratorio),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlightOptions = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(pal = pal_fun, values = ~percentual_laboratorio, opacity = 0.7, title = "Percentuais", position = "bottomright")
m