Como fazer um mapa animado com dados do IBGE

Post para o blog das R-Ladies BH

Code
R
R-Ladies
Spatial
Autor

Marília Melo Favalesso

Data de Publicação

6 de junho de 2020

Como fazer um mapa animado com dados do IBGE ❤

Trabalhando ou não com dados, com certeza você já deve ter ouvido falar sobre o nosso Instituto Brasileiro de Geografia e Estatística (IBGE). O IBGE é uma entidade da administração pública federal, vinculada ao Ministério da Economia, responsável por prover todas as informações estatísticas oficiais do nosso país. Através do seu trabalho analítico, o IBGE nos fornece informações espaço-temporais importantes, como dados sociodemográficos, de ocupação e de uso da terra, sobre a indústria, o meio ambiente e a agricultura, além de cartas e mapas com delimitações do território brasileiro.

Com o objetivo de homenagear a fundação dessa instituição, hoje comemora-se o Dia da Criação do IBGE. Foi em 06 de julho de 1934 que o Decreto de Lei nº 24.609 foi sancionado, iniciando o projeto que se tornou a instituição que conhecemos atualmente. Para que essa data tão importante não passe em branco, hoje eu vou te ensinar a fazer um mapa animado utilizando dados fornecidos pelo IBGE. No meu caso, eu selecionei a variável “população estimada” para os anos entre 2001 e 2019, mas existem outras opções no Sistema IBGE de Recuperação Automática (SIDRA).

População estimada para os municípios brasileiros entre 2001 e 2019 (fonte de dados: SIDRA - IBGE, 2020).


A SIDRA é uma ferramenta digital criada pelo IBGE com o intuito de permitir a consulta, de maneira simples e rápida, aos dados de estudos e pesquisas realizados pelo instituto. A SIDRA conta com uma API que facilita o download dos dados de sua plataforma, porém, existe um limite de 50.000 informações por download, o que impossibilita a transferência direta dos dados de população estimada para o nosso projeto R. Consequentemente, é necessário realizar o download diretamente da plataforma.

Para facilitar o acesso aos dados, deixei a planilha de população estimada hospedada em meu repositório GitHub. Assim, vamos conseguir baixar e trabalhar com os dados diretamente em nosso projeto R.

Você pode rodar o script tanto localmente (seu computador) quanto pelo RStudio cloud, como o Rladies Belo Horizonte divulgou nesse post.

Vamos usar alguns pacotes para fazer o mapa: readr, sp, sf, brazilmaps, cartography, reshape2 e animation. Pode ser que para a instalação de alguns deles você também precise do pacote remotes. Todos em referência no fim do post.

## ~~~ Abrir os dados no R ~~~ ## 

## Pacotes
library(readr) # O 'readr' é um pacote que facilita a obtenção de dados direto de arquivos .csv.

## Vamos salvar o endereço para a planilha de dados em um objeto chamado "myfile". 
myfile <- "https://raw.githubusercontent.com/mmfava/niver_IBGE/master/tab.csv"

## Vamos abrir a planilha com o comando 'read_csv2' e armazenar o conteúdo no objeto 'tab'.
tab <- read_csv2(myfile, # Endereço da planilha de dados.
                col_names = TRUE) # Indicamos que a primeira linha da planilha é o nome das colunas.

## Salvar a planilha 'tab' como um data frame no R. 
tab <- as.data.frame(tab)

## Indicar que as colunas 3 até 19 são valores numéricos. 
is.numeric(tab[,3]) # São valores numéricos? NÃO!
[1] FALSE
tab[,3:19] <- sapply(tab[,3:19], as.numeric) # Transformar as colunas entre 3 e 19 em números. 
str(tab)
'data.frame':   5570 obs. of  19 variables:
 $ cod_ibge : num  1100015 1100023 1100031 1100049 1100056 ...
 $ municipio: chr  "Alta Floresta D'Oeste (RO)" "Ariquemes (RO)" "Cabixi (RO)" "Cacoal (RO)" ...
 $ 2001     : num  26919 76371 7501 73996 18012 ...
 $ 2002     : num  27237 78039 7490 74381 17925 ...
 $ 2003     : num  27563 79680 7478 74758 17794 ...
 $ 2004     : num  29001 86901 7421 76417 17217 ...
 $ 2005     : num  28629 85031 7436 75988 17366 ...
 $ 2006     : num  29005 86924 7421 76422 17215 ...
 $ 2008     : num  24577 84581 6777 78263 16784 ...
 $ 2009     : num  24354 85541 6695 78675 16622 ...
 $ 2011     : num  24228 91570 6221 78959 16939 ...
 $ 2012     : num  24069 92747 6132 79330 16852 ...
 $ 2013     : num  25728 101269 6495 85863 18041 ...
 $ 2014     : num  25652 102860 6424 86556 18013 ...
 $ 2015     : num  25578 104401 6355 87226 17986 ...
 $ 2016     : num  25506 105896 6289 87877 17959 ...
 $ 2017     : num  25437 107345 6224 88507 17934 ...
 $ 2018     : num  23167 106168 5438 84813 16444 ...
 $ 2019     : num  22945 107863 5312 85359 16323 ...

A nossa planilha contém os seguintes dados:

Estimativa populacional para os municípios brasileiros entre 2001 e 2019, segundo o IBGE (fonte: Sidra, 2020)..

A próxima etapa do nosso projeto é a obtenção de polígonos para os municípios do Brasil. Para tal, vamos utilizar dados do tipo ‘sf’ ( spatial data simplified) do pacote ‘brazilmaps’. A parte legal desse pacote é que ele já fornece os limites dos municípios com os códigos do IBGE.

## ~~~ Mapa do Brasil ~~~ ##

## Pacotes
library(sp) # Vai auxiliar o brazilmaps na produção dos mapas.
library(sf) # Vai auxiliar o brazilmaps na produção dos mapas.
library(brazilmaps) # Polígono com os municípios do Brasil.

## Usamos o comando 'get_map' do pacote 'brazilmaps' para 
## a obtenção dos polígonos municipais. 
brasil <- brazilmaps::get_brmap(geo = "City", # Polígonos para municípios.
                    class = "sf") # Classe espacial = 'sf'. 

# Visualização do mapa.
plot(st_geometry(brasil)) 
old-style crs object detected; please recreate object with a recent sf::st_crs()
old-style crs object detected; please recreate object with a recent sf::st_crs()
old-style crs object detected; please recreate object with a recent sf::st_crs()


Para a construção dos mapas, é necessário associar os valores de população estimada com os polígonos que delimitam os municípios brasileiros. Para isso, vamos utilizar o comando “merge” com as colunas que correspondem aos códigos IBGE como chaves.

## ~~~ Unir as tabelas ~~~ ##

## Vamos unir as tabelas a partir dos códigos do IBGE para os municípios.
tab_brasil <- merge(brasil, tab, # Planilhas que queremos unir.
                    by.x = 'City', by.y = 'cod_ibge', # Nome das colunas com os códigos de pareamento (= código IBGE)
                    all.x = TRUE) # Para manter todos os valores da planilha 'x' (= brasil).
old-style crs object detected; please recreate object with a recent sf::st_crs()
head(tab_brasil)
Simple feature collection with 6 features and 24 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -63.61603 ymin: -13.693 xmax: -60.33317 ymax: -9.670769
Geodetic CRS:  +proj=longlat +ellps=GRS80 +no_defs
     City                  nome State MicroRegion MesoRegion Region
1 1100015 ALTA FLORESTA D'OESTE    11       11006       1102      1
2 1100023             ARIQUEMES    11       11003       1102      1
3 1100031                CABIXI    11       11008       1102      1
4 1100049                CACOAL    11       11006       1102      1
5 1100056            CEREJEIRAS    11       11008       1102      1
6 1100064     COLORADO DO OESTE    11       11008       1102      1
                   municipio  2001  2002  2003  2004  2005  2006  2008  2009
1 Alta Floresta D'Oeste (RO) 26919 27237 27563 29001 28629 29005 24577 24354
2             Ariquemes (RO) 76371 78039 79680 86901 85031 86924 84581 85541
3                Cabixi (RO)  7501  7490  7478  7421  7436  7421  6777  6695
4                Cacoal (RO) 73996 74381 74758 76417 75988 76422 78263 78675
5            Cerejeiras (RO) 18012 17925 17794 17217 17366 17215 16784 16622
6     Colorado do Oeste (RO) 21421 20881 20412 18349 18883 18342 18216 17822
   2011  2012   2013   2014   2015   2016   2017   2018   2019
1 24228 24069  25728  25652  25578  25506  25437  23167  22945
2 91570 92747 101269 102860 104401 105896 107345 106168 107863
3  6221  6132   6495   6424   6355   6289   6224   5438   5312
4 78959 79330  85863  86556  87226  87877  88507  84813  85359
5 16939 16852  18041  18013  17986  17959  17934  16444  16323
6 18338 18093  19190  19001  18817  18639  18467  16227  15882
                        geometry
1 MULTIPOLYGON (((-62.05044 -...
2 MULTIPOLYGON (((-62.42262 -...
3 MULTIPOLYGON (((-60.70931 -...
4 MULTIPOLYGON (((-61.21172 -...
5 MULTIPOLYGON (((-60.74296 -...
6 MULTIPOLYGON (((-60.33317 -...


Os mapas com as estimativas populacionais são criados com o uso do pacote “cartography”.

Para facilitar o entendimento do uso do pacote, primeiro vamos criar um mapa com as estimativas populacionais para 2011, deixando a animação para o último passo do projeto.

Cada polígono do mapa denota um município do Brasil. Desse jeito, cada polígono precisa ser colorido com a respectiva informação de população. Sendo assim, vamos criar intervalos da variável tamanho populacional, nos passos abaixo. E, apesar de o mapa inicial ser de 2011 vamos definir os valores dos intervalos da variável tamanho populacional com base no histórico inteiro.

A gente começa selecionando as colunas com as informações propriamente ditas (colunas dos anos) e deixando esse histórico das populações em um formato longo/empilhado:

## ~~~ Mapa com estimativa populacional para 2011 ~~~ ##

## Pacotes:
library(reshape2) ## Para mudar o formato de uma tabela.
library(cartography) ## Para a produção do mapa.

## ~> 1. A primeira etapa é criar um vetor com intervalos de população estimada, considerando os dados para todos os municípios e anos da planilha 'tab_brasil'. 

## Mudamos o formato da tabela com a função "melt", de modo que cada linha descreve um município, de um estado e sua respectiva população
desc <- tab[, 3:19] %>% 
  melt() # Assim, temos anos em uma coluna e estimativa populacional em outra.
No id variables; using all as measure variables
head(desc)
  variable value
1     2001 26919
2     2001 76371
3     2001  7501
4     2001 73996
5     2001 18012
6     2001 21421

Note que a função melt do pacote deixa os dados em formato longo, assim como a função pivot_wider do pacote tidyr.

Agora, definimos os valores dos intervalos da variável tamanho populacional. Se a gente quiser fazer por percentis:

## Utilizamos a função "getBreaks" para obter 10 intervalos de valores. 
breaks_map <- getBreaks(desc$value, # Valores de estimativa populacional para todos municípios e anos.
                        nclass = 10) # Número de intervalos de valores que queremos.
# Vendo como ficou:
breaks_map
 [1]      781.0     3154.0     4534.0     6128.0     8214.0    11117.0
 [7]    14763.6    19874.0    28767.6    54402.4 12252023.0

Devido à grande variabilidade da variável tamanho populacional os intervalos foram definidos, possivelmente de um jeito pouco intuitivo. Por exemplo, todos os municípios com população entre 5.44024^{4} e 1.2252023^{7} habitantes seriam representados de modo semelhante (com a mesma cor) sendo que uma cidade com 12 milhões de habitantes é mais de 200 vezes maior que uma cidade com 55.000 habitantes.

Vou quebrar de outro jeito. Note que eu especifiquei valores segundo uma percepção subjetiva de quais seriam quebras interessantes e passei as quantidades como um vetor.

## Utilizamos a função "getBreaks" para obter 10 intervalos de valores. 
breaks_map <- c(min(desc$value, na.rm = TRUE),
                2500, 5000, 10000, 50000, 100000, 1000000,
                max(desc$value, na.rm = TRUE))

breaks_map
[1]      781     2500     5000    10000    50000   100000  1000000 12252023

E vamos ao mapa!

## ~~ > 2. O mapa. 
## 2.1 Fundo colorido para o mapa. 
## Plotamos as dimensões do Brasil: st_geometry(tab_brasil)
## Não incluir bordas ou cores nesse mapa: col = NA; border = NA
## Colorir em lavanda o nosso background: bg = "lavender"
## Retirar títulos do mapa: main = NULL
plot(st_geometry(tab_brasil), 
     col = NA, 
     border = NA, 
     bg = "lavender", 
     main = NULL)

## Vamos plotar os valores de população para o ano de 2011 com a função "choroLayer" do pacote "cartography".  
## O mapa:
choroLayer(x = tab_brasil, # Tabela com os municípios do Brasil e dados de população estimada (formato "sf"). 
           var = "2011", # Aqui especificamos qual variável queremos plotar no mapa.
           breaks = breaks_map, # Aqui são os intervalos de valores para o mapa.
           col = carto.pal(pal1 = "harmo.pal", n1 = 10), # Palheta de cores selecionada.  
           border = NA, # Sem bordas no mapa. 
           legend.pos = NA, # Sem legendas no mapa. 
           legend.title.txt = NA, # Sem título de legenda no mapa. 
           add = TRUE) # Adicionar o mapa sob o fundo lavanda. 

## A legenda:
legendChoro(pos = "bottomright", # Legenda na parte inferior e direita do mapa. 
            title.txt = "População \nestimada", # Título da legenda. 
            breaks = breaks_map, # Intervalo de valores para a legenda (= mapa). 
            col = carto.pal(pal1 = "harmo.pal", n1 = 10), # Cores legenda (= mapa).
            nodata = TRUE, # Incluir um quadrado branco para 'NA'. 
            nodata.txt = "Sem dados") # Nome dado à legenda de valores faltantes. 

# 3. Informações do nosso mapa:
layoutLayer(title = "Distribuição da população em 2011", # Título do mapa.
            author = "M. M. Favalesso (2020)", # Autor do mapa. 
            sources = "IBGE, estimativa populacional (2020)", # Fonte dos dados (= IBGE ❤)
            scale = NULL, # Sem barras de escala. 
            south = TRUE) # Indicação do sul. 


O último passo do nosso projeto é criar um mapa animado com as estimativas populacionais para os municípios do Brasil. Para tal, vamos usar o pacote “animation”. Esse pacote salva uma sequência de imagens dentro de um laço como um gif animado. Particularmente, é um dos meus pacotes R favoritos.

Se você não estiver usando um projeto (.Rproj) é necessário que você defina um diretório de trabalho para salvar os mapas.

## ~~~ Criando a animação ~~~ ##

## Working directory
## a pasta do seu computador onde vamos salvar nosso gif.
#setwd("pasta_onde_voce_quer_salvar")

## Pacote:
library(animation) ## Pacote para a criação das animações.

## Vetor com o nome das colunas que queremos plotar em nosso laço de repetição, para que apareçam
## em nossa animação em sequência. 
ano <- colnames(tab_brasil)[8:24]

## Usamos um laço de repetição para criar os mapas com as estimativas populacionais e inseri-los na nossa animação.   
saveGIF({
  for(i in ano){ ## Vamos usar a função saveGIF do pacote "animation".
    ## for(i in ano) = Para cada ano (i) no objeto "ano" ...
    
    ## Background colorido.  
    plot(st_geometry(tab_brasil), col = NA, border = NA, bg = "lavender", main = NULL)
    
    ## Mapas de população estimada. 
    choroLayer(x = tab_brasil, 
               var = i, # A cada laço de repetição, um novo ano é plotado. 
               breaks = breaks_map, 
               col = carto.pal(pal1 = "harmo.pal", n1 = 10),  
               border = NA, 
               legend.pos = NA, 
               legend.title.txt = NA, 
               add = TRUE) 
    
    ## Legenda.
    legendChoro(pos = "bottomright",
                title.txt = "População \nestimada",
                breaks = breaks_map,
                col = carto.pal(pal1 = "harmo.pal", n1 = 10), 
                nodata = TRUE, nodata.txt = "Sem dados")
    
    ## Informações do mapa.
    layoutLayer(title = paste0("Distribuição da população em ", i), # Título do mapa para cada ano. 
                author = "M. M. Favalesso (2020)", 
                sources = "IBGE, estimativa populacional (2020)", 
                scale = NULL, 
                south = TRUE)
  }
}, movie.name = "pop_BR.gif") # Nome do gif. 
Output at: pop_BR.gif
[1] TRUE


Com a finalização do laço, o gif é aberto e você poderá verificar o resultado. O arquivo ficará salvo no seu working directory com o nome “pop_brasil.gif”.

Espero que você tenha gostado desse tutorial!

Desejo ver suas gifs animadas em comemoração ao aniversário do nosso IBGE ♡

Um abraço forte!

Revisão por @larissa.sayuri.fcs

Referências

Hadley Wickham, Jim Hester e Romain Francois (2018). readr: Read Rectangular Text Data. R package version 1.3.1. https://CRAN.R-project.org/package=readr

Roger S. Bivand, Edzer Pebesma, Virgilio Gomez-Rubio, 2013. Applied spatial data analysis with R, Second edition. Springer, NY. https://asdar-book.org/

Renato Prado Siqueira (2020). brazilmaps: Brazilian Maps from Different Geographic Levels. R package version 0.1.0. http://github.com/rpradosiqueira/brazilmaps

  • Pacote sp:

Pebesma, E.J., R.S. Bivand, 2005. Classes and methods for spatial data in R. R News 5 (2), https://cran.r-project.org/doc/Rnews/.

  • Pacote sf:

Pebesma, E., 2018. Simple Features for R: Standardized Support for Spatial Vector Data. The R Journal 10 (1), 439-446, https://doi.org/10.32614/RJ-2018-009

Giraud, T. e Lambert, N. (2016). cartography: Create and Integrate Maps in your R Workflow. JOSS, 1(4). doi: 10.21105/joss.00054.

Giraud, T. e Lambert, N. (2017). “Reproducible Cartography.” In Peterson M. (ed.), _Advances in Cartography and GIScience. ICACI 2017. Lecture Notes in Geoinformation and Cart

ography._, pp. 173-183. doi: 10.1007/978-3-319-57336-6_13.

Hadley Wickham (2007). Reshaping Data with the reshape Package. Journal of Statistical Software, 21(12), 1-20. URL http://www.jstatsoft.org/v21/i12/.

Yihui Xie (2013). animation: An R Package for Creating Animations and Demonstrating Statistical Methods. Journal of Statistical Software, 53(1), 1-27. URL http://www.jstatsoft.org/v53/i01/.

Yihui Xie [aut, cre], Christian Mueller [ctb], Lijia Yu [ctb], Weicheng Zhu [ctb] (2018). animation: A Gallery of Animations in Statistics and Utilities to Create Animations. R package version 2.6.

Csárdi G, Hester J, Wickham H, Chang W, Morgan M, Tenenbaum D (2024). remotes: R Package Installation from Remote Repositories, Including ‘GitHub’. R package version 2.5.0, https://github.com/r-lib/remotes#readme, https://remotes.r-lib.org.

Citação

BibTeX
@online{melo_favalesso2020,
  author = {Melo Favalesso, Marília},
  title = {Como fazer um mapa animado com dados do IBGE},
  version = {1},
  date = {2020-06-06},
  url = {http://www.mmfava.com},
  langid = {pt-br}
}
Por favor, cite este trabalho como:
Melo Favalesso, Marília. 2020. “Como fazer um mapa animado com dados do IBGE.” June 6, 2020. http://www.mmfava.com.