Mapas com geobr e leaflet

Guilherme Ferreira
2025-01-09

Apresentação

Pacote geobr

O pacote geobr, desenvolvido e mantido pela equipe do IPEA - Instituto de Pesquisa Econômica Aplicada, disponibiliza funções para obter diversas bases de dados espaciais oficiais do Brasil.

O geobr utiliza elementos cartográficos representados por dados vetoriais para descrever locais específicos(definidos pelos pontos), redes de transporte(definidas pelas linhas) e limites das cidades(definidos pelos polígonos), por exemplo.

Possui diversas funções para a delimitação territorial de entes federativos: read_country() - delimitação do Brasil; read_state(“MG”) - delimitação de um estado específico, usando a sigla como argumento; read_municipality(code_muni = 3136702) - delimitação de um município específico, usando o código do IBGE do município.

Além disso, fornece funções para acesso a diversos datasets: read_schools() - escolas, read_health_facilities() - unidades de saúde, read_census_tract() - setores censitários, dentre outros.

O geobr utiliza o sistema geodésico de referência SIRGAS2000, CRS(4674).

Pacote leaflet

Leaflet é uma biblioteca JavaScript utilizada para a criação de mapas interativos. O pacote leaflet facilita o desenvolvimento de mapas no R, apesar da curva de aprendizagem exigida.

Por padrão, o pacote leaflet usa nativamente o sistema de referência espacial CRS 4326.

Objetivo

Inspirados em Daniel Castro, vamos mapear as escolas públicas de Juiz de Fora/MG, para reproduzir em leaflet o que o autor em comento realizou em ggplot2, mudando a perspectiva de visualização de estática para interativa.

Rotinas

Diretório de trabalho

Para começar, definimos o diretório de trabalho:

setwd("/home/gf/Scripts/Escolas")

Bibliotecas

Depois carregamos as bibliotecas necessárias:

Extração da área de interesse

Delimitamos o polígono do município de Juiz de Fora/MG:

muni_jf <- geobr::read_municipality(code_muni = 'MG', 
                                    year = 2022, 
                                    showProgress = FALSE) |>
  filter(name_muni == "Juiz de Fora")

Dataset

Baixamos os dados de todas as escolas do país:

escolas <- 
  geobr::read_schools(showProgress = F)

Filtramos as escolas públicas do município desejado:

escolas_públicas <- escolas %>% 
  filter(abbrev_state == "MG",
         name_muni == "Juiz de Fora",
         government_level != "Privada",
         service_restriction != "ESCOLA PARALISADA")

Convertemos do CRS atual para o especificado:

escolas_públicas <- escolas_públicas %>% filter(!st_is_empty(.)) %>%
  st_transform(crs = 4326) # Reprojetar para WGS84

Mapa inicial

Criamos um mapa interativo para seleção das escolas por nível de governo ou ente federativo de vinculação administrativa:

# Função para gerar ícones com cor dinâmica com base no nível de governo
gerar_icone <- function(ente_federativo) {
  # Definir a cor do ícone de acordo com o nível de governo
  color <- switch(ente_federativo,
                  "Municipal" = "blue",
                  "Estadual" = "green",
                  "Federal" = "red")
  
  # Gerar ícone com marcador branco e cor do ícone dinâmica
  awesomeIcons(
    icon = 'graduation-cap',    # Ícone de formatura (por exemplo)
    iconColor = color,          # Cor do ícone muda conforme o nível de governo
    markerColor = 'white',      # Cor do marcador é sempre branca
    library = 'fa'        # 
  )
}

# Mapa interativo
leaflet(width = "100%") %>% 
  addTiles() %>%
  setView(-43.365703, -21.762661, zoom = 12) %>%
  # Camada: Municipal
  addAwesomeMarkers(
    data = escolas_públicas %>% filter(government_level == "Municipal"),
    icon = ~gerar_icone("Municipal"),
    label = ~as.character(name_school),
    group = "Municipal"
  ) %>%
  # Camada: Estadual
  addAwesomeMarkers(
    data = escolas_públicas %>% filter(government_level == "Estadual"),
    icon = ~gerar_icone("Estadual"),
    label = ~as.character(name_school),
    group = "Estadual"
  ) %>%
  # Camada: Federal
  addAwesomeMarkers(
    data = escolas_públicas %>% filter(government_level == "Federal"),
    icon = ~gerar_icone("Federal"),
    label = ~as.character(name_school),
    group = "Federal"
  ) %>%
  # Controle de camadas
  addLayersControl(
    overlayGroups = c("Municipal", "Estadual", "Federal"),
    options = layersControlOptions(collapsed = FALSE)
  )  %>%
  
  addFullscreenControl(position = "bottomright")  %>% 
  addResetMapButton()

Distribuição das escolas por etapa educacional

Reestruturamos o data frame:

escola_etapa <- escolas_públicas %>%
  mutate(
    etapa = case_when(
      stringr::str_detect(education_level, "Infantil") ~ "Educação Infantil",
      stringr::str_detect(education_level, "Fundamental") ~ "Ensino Fundamental",
      stringr::str_detect(education_level, "Ensino Médio") ~ "Ensino Médio",
      TRUE ~ NA_character_
    )
  ) %>%
  # Filtrar escolas que atendem uma das etapas
  filter(!is.na(etapa)) %>%
  # Garantir que `etapa` seja um fator com níveis ordenados
  mutate(
    etapa = factor(
      etapa,
      levels = c("Educação Infantil", "Ensino Fundamental", "Ensino Médio")
    )
  ) %>%
  # Reatribuir a classe sf para o objeto final
  sf::st_as_sf()

Criamos o novo mapa, com marcadores circulares:

# Criar a paleta de cores para os níveis de governo
paleta <- colorFactor(
  palette = c("Municipal" = "blue", "Estadual" = "green", "Federal" = "red"),
  domain = escola_etapa$government_level
)


# Criar o mapa interativo
mapa <- leaflet(width = "100%") %>%
  addTiles() %>%
  setView(-43.365703, -21.762661, zoom = 12) %>%
  
  # Camada: Educação Infantil
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Educação Infantil"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    group = "Educação Infantil"
  ) %>%
  
  # Camada: Ensino Fundamental
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Ensino Fundamental"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    group = "Ensino Fundamental"
  ) %>%
  
  # Camada: Ensino Médio
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Ensino Médio"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    group = "Ensino Médio"
  ) %>%
  
  # Adicionar legenda
  addLegend(
    position = "bottomright",
    values = escola_etapa$government_level, # Valores explícitos para o domínio
    pal = paleta,
    opacity = 0.7,
    title = "Administração"
  ) %>%
  
  # Controle de camadas
  addLayersControl(
    overlayGroups = c("Educação Infantil", "Ensino Fundamental", "Ensino Médio"),
    options = layersControlOptions(collapsed = FALSE)
  ) %>% 
  addResetMapButton() %>%
  addFullscreenControl(position = "bottomright")


# Exibir o mapa
mapa

Agrupamos os pontos, para melhorar a visualização:

# Criar a paleta de cores para os níveis de governo
paleta <- colorFactor(
  palette = c("Municipal" = "blue", "Estadual" = "green", "Federal" = "red"),
  domain = escola_etapa$government_level
)


# Criar o mapa interativo
cluster <- leaflet(width = "100%") %>%
  addTiles() %>%
  setView(-43.365703, -21.762661, zoom = 12) %>%
  
  # Camada: Educação Infantil
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Educação Infantil"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    clusterOptions = markerClusterOptions(),
    group = "Educação Infantil"
  ) %>%
  
  # Camada: Ensino Fundamental
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Ensino Fundamental"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    clusterOptions = markerClusterOptions(),
    group = "Ensino Fundamental"
  ) %>%
  
  # Camada: Ensino Médio
  addCircleMarkers(
    data = escola_etapa %>% filter(etapa == "Ensino Médio"),
    radius = 6,
    color = ~paleta(government_level), # Corrigido para usar o subconjunto
    fillOpacity = 0.7,
    label = ~name_school,
    clusterOptions = markerClusterOptions(),
    group = "Ensino Médio"
  ) %>%
  
  # Adicionar legenda
  addLegend(
    position = "bottomright",
    values = escola_etapa$government_level, # Valores explícitos para o domínio
    pal = paleta,
    opacity = 0.7,
    title = "Administração"
  ) %>%
  
  # Controle de camadas
  addLayersControl(
    overlayGroups = c("Educação Infantil", "Ensino Fundamental", "Ensino Médio"),
    options = layersControlOptions(collapsed = FALSE)
  ) %>% 
  addResetMapButton() %>%
  addFullscreenControl(position = "bottomright")


# Exibir o mapa
cluster

Referências:

Castro, D. (2023) Plotando escolas no mapa com R: análise sobre São Paulo/SP. Última atualização em jan. 25, 2023. Acessado em 04/01/2025: https://dlcastro.com/post/plotando-escolas-no-mapa-com-r/.

Cheng, J.; Schloerke, B.; Karambelkar, B.; Xie, Y. (2024) leaflet: Create Interactive Web Maps with the JavaScript ‘Leaflet’ Library. R package version 2.2.2.9000, https://github.com/rstudio/leaflet, https://rstudio.github.io/leaflet/.

Lacko, J. (2024) Leaflet in R: Tips & tricks for interactive maps. Acessado em 04/01/2025: https://www.jla-data.net/eng/leaflet-in-r-tips-and-tricks/.

Pereira, R.H.M.; Gonçalves, C.N.; et. all (2019) geobr: Loads Shapefiles of Official Spatial Data Sets of Brazil. GitHub repository - https://github.com/ipeaGIT/geobr.