Importando dados do SIDRA

Importando dados abertos do IBGE via API usando o sidrar no R.
data-science
economia
tutorial-R
Author

Vinicius Oike

Published

August 10, 2023

O SIDRA, ou Sistema IBGE de Recuperação Automática, é um sistema automatizado de coleta de dados do IBGE, que disponbiliza tabelas das várias pesquisas feitas pelo IBGE. O sistema é centralizado no site. Encontrar pesquisas e dados pode não ser fácil e, em geral, exige conhecimento prévio sobre as pesquisas do IBGE. O site oferece uma página de ajuda.

Neste post vou comentar mais especificamente sobre o pacote sidrar que dialoga diretamente com a API do SIDRA para importar tabelas diretamente para dentro do R. O pacote tem duas funções centrais:

R

Primeiro, temos que instalar o pacote sidrar e chamá-lo usando a função library(). Além disso, para a primeira parte deste tutorial mostro também como utilizar os pacotes dplyr, tidyr e janitor para limpar os dados.

# Instale o pacote (caso necessário)
install.packages("sidrar")
# Outros pacotes usados neste tutorial
install.packages(c("janitor", "dplyr", "tidyr"))

library("sidrar")
library("janitor")
library("dplyr")
library("tidyr")

Importando dados

Vamos começar olhando para a tabela de estimativas da população dos municípios. A tabela 6579 reúne os dados da pesquisa “Estimativas da População”, uma contagem anual da população de todos os municípios do Brasil.

Primeiro vamos usar a função info_sidra para verificar o conteúdo desta tabela.

info_sidra(6579)
$table
[1] "Tabela 6579: População residente estimada"

$period
[1] "2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021"

$variable
   cod                                   desc
1 9324 População residente estimada (Pessoas)

$classific_category
NULL

$geo
     cod                      desc
1 Brazil                Brasil (1)
2 Region         Grande Região (5)
3  State Unidade da Federação (27)
4   City         Município (5.570)

A tabela, neste caso, é bastante simples. Os dados são anuais e estão disponíveis de 2001 a 2021. Há apenas uma variável: População residente estimada (Pessoas) com código 9324. Por fim, os dados estão desagregados no nível nacional, regional, estadual e municipal.

Vamos importar a população de todos os municipios em 2021. Note que no código abaixo o argumento do ano é inserido como um character.

pop21 <- get_sidra(6579, period = "2021", geo = "City")

pop21

A tabela já vem formatada dentro do R.

pop21 <- get_sidra(6579, period = "2021", geo = "City")
head(pop21)
  Nível Territorial (Código) Nível Territorial Unidade de Medida (Código)
2                          6         Município                         45
3                          6         Município                         45
4                          6         Município                         45
5                          6         Município                         45
6                          6         Município                         45
7                          6         Município                         45
  Unidade de Medida  Valor Município (Código)                  Município
2           Pessoas  22516            1100015 Alta Floresta D'Oeste - RO
3           Pessoas 111148            1100023             Ariquemes - RO
4           Pessoas   5067            1100031                Cabixi - RO
5           Pessoas  86416            1100049                Cacoal - RO
6           Pessoas  16088            1100056            Cerejeiras - RO
7           Pessoas  15213            1100064     Colorado do Oeste - RO
  Ano (Código)  Ano Variável (Código)                     Variável
2         2021 2021              9324 População residente estimada
3         2021 2021              9324 População residente estimada
4         2021 2021              9324 População residente estimada
5         2021 2021              9324 População residente estimada
6         2021 2021              9324 População residente estimada
7         2021 2021              9324 População residente estimada

Ainda que os dados não estejam “sujos”, eles não estão num formato agradável para se trabalhar. Vamos fazer uma limpeza básica dos dados. Primeiro, vamos simplificar os nomes das colunas e selecionar apenas as colunas de maior interesse.

pop21 <- janitor::clean_names(pop21)
pop21 <- dplyr::select(pop21, municipio_codigo, municipio, ano, valor)
municipio_codigo municipio ano valor
2 1100015 Alta Floresta D'Oeste - RO 2021 22516
3 1100023 Ariquemes - RO 2021 111148
4 1100031 Cabixi - RO 2021 5067
5 1100049 Cacoal - RO 2021 86416
6 1100056 Cerejeiras - RO 2021 16088
7 1100064 Colorado do Oeste - RO 2021 15213

Note que o nome dos municípios contém também a abreviação do estado ao qual o município pertence. Podemos deixar isto mais claro separando esta informação em duas colunas distintas.

pop21 <- tidyr::separate(
  pop21,
  col = "municipio",
  into = c("nome_muni", "abr_estado"),
  sep = " - ")
municipio_codigo nome_muni abr_estado ano valor
2 1100015 Alta Floresta D'Oeste RO 2021 22516
3 1100023 Ariquemes RO 2021 111148
4 1100031 Cabixi RO 2021 5067
5 1100049 Cacoal RO 2021 86416
6 1100056 Cerejeiras RO 2021 16088
7 1100064 Colorado do Oeste RO 2021 15213

Por fim, podemos padronizar melhor o nome das colunas. Vamos utilizar as convenções do pacote geobr, por exemplo, e traduzir as variáveis para o inglês.

pop21 <- dplyr::rename(
  pop21,
  name_muni = nome_muni,
  abbrev_state = abr_estado,
  code_muni = municipio_codigo,
  year = ano,
  population = valor)

A tabela final aparece abaixo.

code_muni name_muni abbrev_state year population
2 1100015 Alta Floresta D'Oeste RO 2021 22516
3 1100023 Ariquemes RO 2021 111148
4 1100031 Cabixi RO 2021 5067
5 1100049 Cacoal RO 2021 86416
6 1100056 Cerejeiras RO 2021 16088
7 1100064 Colorado do Oeste RO 2021 15213

A padronização dos nomes traz como vantagem facilitar o join com o shapefile dos municípios usando o pacote geobr.

Variando os parâmetros de busca

A função get_sidra() permite refinar a query que gera a tabela final que é importada dentro do R. Os principais argumentos são:

  • period - escolhe a janela temporal dos dados.
  • variable - escolhe a variável a ser importada.
  • geo - nível geográfico dos dados (e.g. "Brazil", "City", "Neighborhood", etc.).
  • geo.filter - lista com filtros geográficos.
  • classific - classificação dos dados.
  • category - escolhe quais categorias (do classific) importar.

De maneira geral, todos os parâmetros acima tem algumas nuances. Vamos explorá-los caso a caso

Importando dados de vários períodos

Para selecionar múltiplos períodos podemos montar um vetor character com os períodos desejados. Para selecionar uma sequência de períodos deve-se montar um string único encadeando os períodos com o sinal de “-”. O código abaixo deve deixar isto mais claro.

Note que se você rodar o código abaixo, provavelmente, vai enfrentar um problema de limite de query. A API do SIDRA restringe o número de linhas que um usuário pode chamar de uma só vez. Assim, para importar bases de dados maiores é preciso montar estratégias para particionar os dados.

# Importa os dados de 2010 e de 2020
pop <- get_sidra(6579, period = c("2010", "2020"), geo = "City")

# Importa todos os dados de 2010 até 2020 (erro: limite de requisição)
pop <- get_sidra(6579, period = c("2010-2020"), geo = "City")

Um detalhe curioso é que a função não retorna erros quando o período extrapola os valores disponíveis nos dados. Assim a função abaixo retorna apenas os valores de 2021.

# Importa todos os dados de 2021 até 2030
pop <- get_sidra(6579, period = c("2021-2030"), geo = "City")

A mesma lógica acima vale para quando os dados são mensais ou trimestrais. Considere o exemplo da taxa de desocupação, levantada pela PNADC Trimestral. Note que os períodos estão no formato YYYYQQ.

info_sidra(4099)

Vamos importar todos as observações da taxa de desocupação em 2012. Note que agora há múltiplas variáveis na mesma tabela e que o resultado já está em formato “long”.

unemp <- get_sidra(4099, period = "201201-201204")
head(unemp)
  Nível Territorial (Código) Nível Territorial Unidade de Medida (Código)
2                          1            Brasil                          2
3                          1            Brasil                          2
4                          1            Brasil                          2
5                          1            Brasil                          2
6                          1            Brasil                          2
7                          1            Brasil                          2
  Unidade de Medida Valor Brasil (Código) Brasil Trimestre (Código)
2                 %   8.0               1 Brasil             201201
3                 %   0.9               1 Brasil             201201
4                 %  15.3               1 Brasil             201201
5                 %   0.7               1 Brasil             201201
6                 %  14.0               1 Brasil             201201
7                 %   0.7               1 Brasil             201201
          Trimestre Variável (Código)
2 1º trimestre 2012              4099
3 1º trimestre 2012              4103
4 1º trimestre 2012              4114
5 1º trimestre 2012              4115
6 1º trimestre 2012              4116
7 1º trimestre 2012              4117
                                                                                                                                                                           Variável
2                                                                                             Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
3                                                                   Coeficiente de variação - Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
4                           Taxa combinada de desocupação e de subocupação por insuficiência de horas trabalhadas, na semana de referência, das pessoas de 14 anos ou mais de idade
5 Coeficiente de variação - Taxa combinada de desocupação e de subocupação por insuficiência de horas trabalhadas, na semana de referência, das pessoas de 14 anos ou mais de idade
6                                                     Taxa combinada de desocupação e força de trabalho potencial, na semana de referência, das pessoas de 14 anos ou mais de idade
7                           Coeficiente de variação - Taxa combinada de desocupação e força de trabalho potencial, na semana de referência, das pessoas de 14 anos ou mais de idade

Para refinar a busca acima temos de usar o argumento variable.

unemp <- get_sidra(4099, period = "201201-202203", variable = 4099)
head(unemp)
  Nível Territorial (Código) Nível Territorial Unidade de Medida (Código)
2                          1            Brasil                          2
3                          1            Brasil                          2
4                          1            Brasil                          2
5                          1            Brasil                          2
6                          1            Brasil                          2
7                          1            Brasil                          2
  Unidade de Medida Valor Brasil (Código) Brasil Trimestre (Código)
2                 %   8.0               1 Brasil             201201
3                 %   7.6               1 Brasil             201202
4                 %   7.1               1 Brasil             201203
5                 %   6.9               1 Brasil             201204
6                 %   8.1               1 Brasil             201301
7                 %   7.5               1 Brasil             201302
          Trimestre Variável (Código)
2 1º trimestre 2012              4099
3 2º trimestre 2012              4099
4 3º trimestre 2012              4099
5 4º trimestre 2012              4099
6 1º trimestre 2013              4099
7 2º trimestre 2013              4099
                                                                               Variável
2 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
3 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
4 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
5 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
6 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
7 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade

Agora temos a série completa apenas da taxa de desocupação no Brasil. Podemos buscar também a taxa em cada uma das cidades do Brasil.

unemp <- get_sidra(
  4099,
  period = "201201-202203",
  variable = 4099,
  geo = "City"
  )
  Nível Territorial (Código) Nível Territorial Unidade de Medida (Código)
1                          6         Município                          2
2                          6         Município                          2
3                          6         Município                          2
4                          6         Município                          2
5                          6         Município                          2
6                          6         Município                          2
  Unidade de Medida Valor Município (Código)        Município
1                 %   9.0            1100205 Porto Velho - RO
2                 %  10.4            1200401  Rio Branco - AC
3                 %  12.9            1302603      Manaus - AM
4                 %   9.3            1400100   Boa Vista - RR
5                 %  10.5            1501402       Belém - PA
6                 %  12.6            1600303      Macapá - AP
  Trimestre (Código)         Trimestre Variável (Código)
1             201201 1º trimestre 2012              4099
2             201201 1º trimestre 2012              4099
3             201201 1º trimestre 2012              4099
4             201201 1º trimestre 2012              4099
5             201201 1º trimestre 2012              4099
6             201201 1º trimestre 2012              4099
                                                                               Variável
1 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
2 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
3 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
4 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
5 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade
6 Taxa de desocupação, na semana de referência, das pessoas de 14 anos ou mais de idade

Note, contudo, que temos o resultado somente nas capitais. Apesar do argumento “City” ser o mesmo que usamos na pesquisa de Estimativas da População, aqui o argumento “City” retorna apenas as capitais. Isto acontece porque a PNADC é uma pesquisa que é feita apenas nas capitais brasileiras e não tem uma desagregação a nível municipal para todos os municípios do Brasil. Este importante detalhe não fica evidente e depende do conhecimento prévio do usuário a respeito das pesquisas do IBGE.

Importando muitos dados

Como comentei acima, a API do SIDRA tem um limite de linhas nas queries. Isto significa que é preciso montar algumas estratégias para pegar as tabelas em partes menores. Na prática, isto vai depender muito da tabela e da informação que se quer.

O exemplo abaixo é bastante simples mas pode eventualmente ser útil em alguma outra aplicação. O código importa a tabela de estimativas populacionais ano a ano. O mesmo poderia ter sido feito num for-loop, mas prefiro usar o lapply por simplicidade.

Para acelerar o processo pode-se trocar o lapply por parallel::mclapply que roda a função em paralelo. Contudo, na minha experiência, esta estratégia acaba resultando em erros imprevistos. Não sei se isto é resultado de alguma restrição da API. Na prática, é mais seguro evitar o mclapply.

# Define um vetor com todos os anos da pesquisa
periods <- seq(2001:2021)
# Converte para character
periods <- as.character(periods)
# Aplica a função get_sidra a cada elemento de periods (a cada ano)
req <- lapply(periods, function(p) get_sidra(6579, period = p, geo = "City"))
# Junta o resultado numa única tabela
tab <- dplyr::bind_rows(req)

Refinando a busca em casos complexos

Tabelas do Censo

Tabelas que vem do Censo costumam ter maior complexidade. Considere, por exemplo, a tabela 1378, que retorna a população residente, por situação do domicílio (urbano x rural), sexo e idade, segundo a condição no domicílio e compartilhamento da responsabilidade (responsável, cônjuge, filho, etc.)

O resultado da função abaixo é omitido para poupar espaço pois a saída é muito grande. Em casos como este é muito importante filtrar o resultado para conseguir uma tabela que faça sentido.

info_sidra(1378)

Vamos nos focar somente na população residente (var 93) de pessoas responsáveis do domicílio (cod 11941) por bairro de Porto Alegre (4314902).

resp <- get_sidra(
  1378,
  variable = 93,
  classific = c("c455"),
  geo = "Neighborhood",
  geo.filter = list("City" = 4314902)
  )

Após um pouco de limpeza no nome das colunas podemos ver o resultado abaixo.

bairro cond_domi sexo idade situacao_domi valor
2 Medianeira Total Total Total Total 11568
3 Medianeira Pessoa responsável Total Total Total 4206
4 Medianeira Pessoa responsável - com responsabilidade compartilhada Total Total Total 1054
5 Medianeira Pessoa responsável - sem responsabilidade compartilhada Total Total Total 3152
6 Medianeira Cônjuge ou companheiro(a) Total Total Total 2101
7 Medianeira Cônjuge ou companheiro(a) - de sexo diferente Total Total Total 2094
8 Medianeira Cônjuge ou companheiro(a) - de mesmo sexo Total Total Total 7
9 Medianeira Filho(a) Total Total Total 3429
10 Medianeira Filho(a) - da pessoa responsável e do cônjuge Total Total Total 1916
11 Medianeira Filho(a) - somente da pessoa responsável Total Total Total 1513
12 Medianeira Enteado(a) Total Total Total 145
13 Medianeira Genro ou nora Total Total Total 170
14 Medianeira Pai, mãe, padastro ou madrasta Total Total Total 183
15 Medianeira Sogro(a) Total Total Total 51
16 Medianeira Neto(a) Total Total Total 549

Note que temos a coluna da condição do domicílio desagregada (c455), mas todas as outras (sexo, idade, etc.) estão agregadas.

API do SIDRA

Então imagine, por exemplo, que queremos esta mesma informação, por grupos de idade. Esta requisição quebra o limite da query. Além disso, os grupos de idade disponíveis são caóticos e não é possível filtrar dentro deste grupo da mesma maneira como fazemos com o argumento variable.

A solução é interagir diretamente com a API do SIDRA! O código acaba sendo bastante complexo/confuso. Muito provavelmente há maneiras de melhorar o código abaixo, mas foi como fiz para conseguir esta informação. Por conveniência chamo explicitamente todos os pacotes que uso. A limpeza dos dados foi a parte mais desafiadora do processo visto que não foi possível transformar o input de JSON para um data.frame de maneira direta.

Em partes, acho que dei o azar de ter escolhido uma tabela especialmente complicada. Se jsonlite::fromJSON(x, simplifyDataFrame = TRUE) tivesse funcionado, o código seria muito mais simples.

Code
# Bibliotecas usadas
library(dplyr)
library(tidyr)
library(stringr)
library(janitor)
library(tidyjson)
library(httr)
library(jsonlite)
library(geobr)

# 1. Montar a query

# Montar um vetor com o código de todos os bairros de Porto Alegre

# Importa o shapefile de todos os bairros IBGE (2010)
bairros <- geobr::read_neighborhood()

bairros_poa <- bairros |> 
  # Pega apenas os códigos dos bairros de POA
  filter(code_muni == 4314902) |> 
  # O código do bairro tem alguns números sobrando no meio
  mutate(code_nb = paste0(
    str_sub(code_neighborhood, 1, 7),
    str_sub(code_neighborhood, 10, 12))
    )
# Extrai o vetor com os códgios dos bairros
codenb_poa <- bairros_poa[["code_nb"]]
# Colapsa o vetor num único string separado por vírgulas
local = paste(codenb_poa, collapse = ",")
# Insere o string no formato da API
local = stringr::str_glue("localidades=N102[{local}]")

# Base do url da API
base = "https://servicodados.ibge.gov.br/api/v3/agregados"
# Número da tabela
table <- 1378
# Período da extração (ano)
period <- 2010
# Código da variável (Pessoas residentes)
variable <- 93
# Códigos das classes
class <- c(1, 2, 287, 455)
# Filtro das classes (veja info_sidra(1378))
category <- list(c(1), c(4, 5), c(93087:93100), c(11941))
# Colapsa os strings
category <- sapply(category, paste, collapse = ",")
# Coloca os strings no format da API
cat_filter <- stringr::str_glue("{class}[{category}]")
# Colapsa os strings num único string separado pelo operador booleano |
cat_filter <- paste(cat_filter, collapse = "|")

# Monta a query
query <- stringr::str_glue(
  "{base}/{table}/periodos/{period}/variaveis/{variable}?{local}&classificacao={cat_filter}"
)

# 2. Importar dados

# Importar os dados da API
req <- httr::GET(url = query)
json <- httr::content(req, as = "text", encoding = "UTF-8")
json <- jsonlite::fromJSON(json, simplifyVector = FALSE)

# 3. Limpar os dados

# Simplificar os dados de JSON para um tibble
valores <- json |> 
  spread_all() |> 
  enter_object(resultados) |> 
  gather_array() |> 
  spread_all() |> 
  enter_object(series) |> 
  gather_array() |> 
  spread_all()

# Extrair somente os valores da série
valores <- valores |> 
  as_tibble() |> 
  mutate(serie.2010 = as.numeric(serie.2010)) |> 
  pivot_wider(
    id_cols = "array.index",
    names_from = "localidade.id",
    values_from = "serie.2010"
  )

# Extrair a classificação das variáveis (sexo, idade)
classificacao <- json |> 
  spread_all() |> 
  enter_object(resultados) |> 
  gather_array() |> 
  spread_all() |> 
  enter_object(classificacoes) |> 
  gather_array() |> 
  spread_all()

# Extrai somente a coluna com os grupos de idade
tblage <- classificacao |> 
  select(contains("93")) |>
  as_tibble() |> 
  unite("age_group", everything(), na.rm = TRUE) |> 
  filter(age_group != "") |> 
  distinct()

# Cria um grid com todas as classificações na ordem correta
tblclass <- expand_grid(
  situacao_domicilio = "urban",
  resp = "Responsável pelo Domicilio",
  sex = c("male", "female"),
  age_group = tblage$age_group
)

# Junta as classificações com os valores 
tab <- cbind(valores, tblclass)

# Converte os dados para wide
tab <- tab |> 
  pivot_longer(starts_with("431"), names_to = "code_nb") |> 
  select(code_nb, situacao_domicilio, resp, sex, age_group, value)

# Converte os dados para uma tabela final
respnb <- tab |> 
  pivot_wider(
    id_cols = c("code_nb", "age_group"),
    names_from = "sex",
    values_from = "value"
  ) |> 
  mutate(total = male + female)|> 
  group_by(code_nb) |> 
  mutate(total_nb = sum(total)) |> 
  ungroup() |> 
  mutate(share_nb = total / total_nb * 100)

A tabela abaixo mostra o resultado final do código. A tabela apresenta o número total de pessoas responsáveis por domicílios em grupos de idade quinquenais por sexo e por bairro de Porto Alegre. Além disso, a coluna total_nb traz o número total de pessoas responsáveis por domicílio no bairro e share_nb computa a participação relativa de cada faixa de idade no total do bairro.

code_nb age_group male female total total_nb share_nb
4314902003 20 a 24 anos 383 406 789 8757 9
4314902005 20 a 24 anos 3 7 10 435 2
4314902007 20 a 24 anos 214 245 459 9116 5
4314902069 20 a 24 anos 42 62 104 2071 5
4314902009 20 a 24 anos 331 359 690 13137 5
4314902072 20 a 24 anos 75 57 132 3706 4
4314902068 20 a 24 anos 163 144 307 8052 4
4314902013 20 a 24 anos 193 177 370 6319 6
4314902012 20 a 24 anos 31 19 50 2719 2
4314902004 20 a 24 anos 206 227 433 13342 3
4314902032 20 a 24 anos 261 285 546 12171 4
4314902022 20 a 24 anos 117 105 222 6910 3
4314902071 20 a 24 anos 49 29 78 NA NA
4314902045 20 a 24 anos 70 56 126 4190 3
4314902049 20 a 24 anos 71 65 136 4365 3

Apesar de claramente não ser o foco do post, pareceu um desperdício de esforço não fazer algo com esta informação. O código abaixo agrupa os dados um pouco mais e monta um mapa interativo dos domicílios por grupo de idade da pessoa responsável. Não seria difícil transformar isto num aplicativo para ver esta mesma info nas outras faixas de idade, mas isto fica para outro post.

Code
bairros <- geobr::read_neighborhood(showProgress = FALSE)

bairros_poa <- bairros |> 
  # Pega apenas os códigos dos bairros de POA
  filter(code_muni == 4314902) |> 
  # O código do bairro tem alguns números sobrando no meio
  mutate(code_nb = paste0(
    stringr::str_sub(code_neighborhood, 1, 7),
    stringr::str_sub(code_neighborhood, 10, 12))
    )


respnb <- respnb |>
  separate(age_group, into = c("age_min", "age_max"), sep = " a ") |> 
  mutate(
    age_generation = case_when(
      age_min >= 25 & age_min < 40 ~ "25-39",
      age_min >= 40 & age_min < 60 ~ "40-59",
      age_min >= 60 & age_min < 80 ~ "60-79",
      age_min >= 80 ~ "80+",
      TRUE ~ "<25"
    )
  )

resp_grouped_nb <- respnb |> 
  group_by(code_nb, age_generation) |> 
  summarise(pop = sum(total, na.rm = TRUE)) |> 
  group_by(code_nb) |> 
  mutate(total_nb = sum(pop)) |> 
  ungroup() |> 
  mutate(share_nb = pop / total_nb * 100)

resp_ages <- pivot_wider(
  resp_grouped_nb,
  id_cols = "code_nb",
  names_from = "age_generation",
  names_prefix = "age_",
  values_from = "share_nb"
)

resp_ages <- janitor::clean_names(resp_ages)

resp_bairros <- left_join(bairros_poa, resp_ages, by = "code_nb")

O mapa é gerado pelo código abaixo. O mapa mostra o share de domicílios, em cada bairro, que são chefiados por “adultos-jovens”, isto é, de 25 a 39 anos. Nota-se que os bairros que tem maiores percentuais estão mais na periferia da cidade. Alguns bairros de classe alta como Moinhos de Vento, Três Figueiras e Vila Assunção tem os menores percentuais.

Code
library(tmap)
library(tmaptools)
tmap_mode(mode = "view")

m <- tm_shape(resp_bairros) +
  tm_fill(
    col = "age_25_39",
    palette = "inferno",
    alpha = 0.8,
    style = "jenks",
    n = 7,
    id = "name_neighborhood",
    title = "Percentual de domicílios<br>chefiados por pessoas<br>de 25 a 39 anos (%).",
    popup.vars = c(
      "Menos de 25 anos" = "age_25",
      "25 a 39 anos" = "age_25_39",
      "40 a 59 anos" = "age_40_59",
      "60 a 79 anos" = "age_60_79",
      "80 anos ou mais" = "age_80"),
    popup.format = list(digits = 1),
    legend.format = list(digits = 0)) +
  tm_borders() +
  tm_basemap(server = "CartoDB.Positron") +
  tm_view(set.view = c(-51.179152, -30.025976, 13))

leaf <- tmap_leaflet(m)
widgetframe::frameWidget(leaf, width = "100%")