Criando um mapa do Brasil no R em 7 passos

Atualmente as áreas de análise e visualização de dados geográficos vêm sendo bastante exploradas por analistas, estatísticos e cientistas de dados devido à quantidade de recursos disponíveis e pela facilidade no entendimento que é proporcionada ao visualizar dados sobre mapas.

Neste post vamos demonstrar em 7 passos como gerar um mapa do Brasil interativo, usando a ferramenta R, para apresentar a distribuição dos pontos ganhos pelos clubes no Campeonato Brasileiro de futebol desde 2003, na visão por estado.

1) Fazer download do shapefile do Brasil no site do IBGE

Inicialmente precisamos importar para o R o shapefile do mapa do Brasil, que está disponível no site do IBGE. No exemplo vamos utilizar o mapa com a distribuição por estado, porém no site há diversos outros tipos de mapa, como mapas de cada estado com divisão por município, entre outros.

Para encontrar o mapa do Brasil por estado, vamos utilizar a URL abaixo e navegar pelo diretório de pastas do site até encontrar o arquivo br_unidades_da_federacao.zip (imagem a seguir):

http://downloads.ibge.gov.br/downloads_geociencias.htm

Vamos navegar pelo seguinte diretório:

organizacao_do_territorio >>> malhas_territoriais >>> malhas_municipais >>> municipio_2015 >>> Brasil >>> BR >>> br_unidades_da_federacao.zip

ibge_site

Diretório de pastas no site do IBGE

Após fazer o download, iremos extrair os cinco arquivos e copiá-los para o diretório de trabalho do R (no nosso exemplo, será criada uma pasta chamada “Mapa”), para que  assim eles possam ser importados.

2) Importar o shapefile para o R

Agora temos que importar o nosso shapefile para o R, atribuindo a uma variável chamada “shp”. Utilizaremos a função readOGR para esta tarefa:

shp <- readOGR("Mapa\\.", "BRUFE250GC_SIR", stringsAsFactors=FALSE, encoding="UTF-8")

Podemos verificar executando o comando class(shp) que o objeto “shp” é do tipo “SpatialPolygonsDataFrame”. Este é o tipo de objeto que precisamos criar para gerar mapas no R.

3) Importar o dataset que possui os dados que serão plotados no mapa

Outra etapa necessária é importar o arquivo que possui os dados que queremos exibir no mapa. No caso deste exemplo, temos um arquivo chamado “ClassificacaoPontosCorridos.csv” que tem dados dos pontos ganhos por cada clube no Campeonato Brasileiro desde 2003.

O script abaixo realiza a importação do arquivo e realiza a sumarização dos pontos ganhos por estado, utilizando as funções do o pacote dplyr:

pg <- read.csv("Dados\\ClassificacaoPontosCorridos.csv", header=T,sep=";")

pg <- pg %>% group_by(Estado) %>% mutate(cumsum = cumsum(PG))
pg <- pg %>%
  group_by(Estado) %>%
  summarise(Score= max(Score))

pg <- as.data.frame(pg)

Podemos verificar executando o comando class(pg) que a variável “pg” é do tipo de dados “data.frame”. Este é um dos tipos de dados mais comuns no R para armazenar tabelas, porém para trabalhar com mapas precisaremos unir esta variável ao objeto de tipo espacial criado no passo 2.

4) Importar os códigos do IBGE e adicionar ao dataset

O shapefile do IBGE que importamos no passo 2 não possui o campo  “UF”, que é o campo utilizado para identificar o estado no nosso dataset. Teremos então que utilizar um campo chamado “CD_GEOCUF”, que é um código numérico do IBGE para identificar o estado. Para conseguirmos relacionar nosso dataset com o shapefile, iremos realizar a importação de um arquivo CSV que tenha estes códigos numéricos e realizar um “merge” entre este arquivo CSV (variável “ibge”) e o nosso dataset (variável “pg”), para associar os dados pelo campo UF:

ibge <- read.csv("Dados\\estadosibge.csv", header=T,sep=",")

pg <- merge(pg,ibge, by.x = "Estado", by.y = "UF")

Após esta operação, o data frame ficou conforme a imagem abaixo:

tabela_pontos

Data frame com o campo “Código.UF”

5) Fazer a junção entre o dataset e o shapefile utilizando o código do IBGE

Tendo o código do IBGE no nosso objeto “pg”, podemos então unir os nossos dados ao objeto do tipo espacial do R. Ou seja, iremos realizar um “merge” entre a variável “shp” (shapefile) e a variável “pg” (dataset de pontos ganhos). Esta junção irá retornar um data frame espacial, e terá os dados que precisamos para exibir no mapa.

brasileiropg <- merge(shp,pg, by.x = "CD_GEOCUF", by.y = "Código.UF")

Para se ter uma ideia, segue abaixo a imagem do RStudio de como o R armazena os dados em um data frame espacial:

dataframe_espacial

Objeto do tipo “SpatialPolygonsDataFrame”

6) Realizando o tratamento e a formatação do data frame espacial

Agora iremos realizar as últimas transformações no objeto antes de gerar o mapa. A primeira é passar as coordenadas de latitude e longitude para o objeto, utilizando a função proj4string ; a segunda é converter os dados da coluna “NM_ESTADO” para a formatação UTF-8, e a terceira é substituir os valores para os estados que não tem nenhum ponto ganho de “NA” para zero.

proj4string(brasileiropg) <- CRS("+proj=longlat +datum=WGS84 +no_defs")

Encoding(brasileiropg$NM_ESTADO) <- "UTF-8"

brasileiropg$Score[is.na(brasileiropg$Score)] <- 0

7) Gerando o mapa

Finalizadas as etapas de importação e organização dos dados, podemos finalmente gerar o nosso mapa.

Inicialmente vamos escolher as cores para o nosso mapa. Utilizando o pacote RColorBrewer temos acesso a várias paletas de cores. Para consultá-las, basta utilizar no R o comando display.brewer.all():

rcolorbrewer

Paleta de cores do pacote “RColorBrewer”

No nosso exemplo será escolhida a paleta de cores (“Blues”).

Para plotar o mapa existem várias opções de pacotes disponíveis no R. No nosso caso vamos utilizar o pacote Leaflet, que possui uma boa interatividade (é possível clicar nos estados e visualizar os valores de pontuação).

O script para gerar o mapa ficou desta forma:

pal <- colorBin("Blues",domain = NULL,n=5) #cores do mapa

state_popup <- paste0("<strong>Estado: </strong>", 
                      brasileiropg$NM_ESTADO, 
                      "<br><strong>Pontos: </strong>", 
                      brasileiropg$Score)
leaflet(data = brasileiropg) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(fillColor = ~pal(brasileiropg$Score), 
              fillOpacity = 0.8, 
              color = "#BDBDC3", 
              weight = 1, 
              popup = state_popup) %>%
  addLegend("bottomright", pal = pal, values = ~brasileiropg$Score,
            title = "Pontos Conquistados",
            opacity = 1)

O mapa gerado ficou conforme a imagem abaixo:

mapa_pontos

Mapa de pontos ganhos no Campeonato Brasileiro por estado

Observações:

Os scripts e os arquivos necessários para reproduzir este exemplo se encontram neste diretório do GitHub . O script foi testado na versão R-3.3.2. Lembre-se de instalar no R os pacotes necessários!

Este mapa está publicado na web através de um aplicativo no Shiny (isto já é assunto para um outro post…). Quem quiser visualizar e interagir com o mapa, basta clicar aqui.

Referências:

The leaflet package for online mapping in R

21 pensamentos sobre “Criando um mapa do Brasil no R em 7 passos

    • Olá Tomás, tudo bem?

      Muito pertinente sua pergunta. No exemplo do post, estamos fazendo a junção do shapefile com os nossos dados através do código do IBGE. Se você quiser manter essa lógica, você precisará ter um arquivo com os códigos do IBGE de todos os municípios que você quer que apareçam no seu mapa. Aí seria preciso apenas substituir o arquivo “estados.csv” pelo seu arquivo de municípios no comando.
      Caso você não consiga estes códigos do IBGE, você pode tentar fazer a junção por outra coluna, como o nome do município. Porém, há uma chance maior de erro caso ocorra alguma diferença entre os nomes. Nesse caso você teria que alterar as colunas que são usadas pelo comando merge abaixo:

      brasileiropg <- merge(shp,pg, by.x = "CD_GEOCUF", by.y = "Código.UF")

      Obrigado pelo comentário!

  1. Boa noite Marcos! Excelente o seu post!!

    Consegui gerar o mapa no rStudio, mas quando incluo o código em uma aplicação shiny dá esse erro: “ERROR: input string 1 is invalid UTF-8”.

    Fiquei em dúvida sobre apresentar o resultado e utilizei “output$out_pl_mapa_brasil <- renderPlot({".

    Desde já agradeço o apoio!

    • Olá Cleria.

      Que legal você ter conseguido gerar o mapa!

      Sobre a aplicação do Shiny, ainda preciso escrever um post sobre isso, mas ideia seria criar o arquivos ui.R, server.R e global.R e adicionar os comandos nestes arquivos. Também realizei a conversão dos arquivos .csv para .rds, formato de arquivos de dados do próprio R, para facilitar a publicação no Shiny.
      Se você tiver um conhecimento básico de Shiny e quiser testar, adicionei os arquivos que utilizei no seguinte diretório do Github: https://github.com/mvbfontes/mapabrasil/tree/master/Shiny.
      Ainda vou realizar a revisão dessa solução. Caso ocorra algum problema, me mande um feedback que tento te ajudar.

      Abraços!

      • o arquivo brasileiropg.rds vc faz ele quando? estou usando seu exemplo para um trabalho da faculdade no qual troquei o seu csv pelo csv dos meus dados, e gostaria de usar o seu shiny =) Mas não sei quando e o que salvar em .rds para gerar a visualização

  2. Olá Wesley!

    Essa parte seria para converter os arquivos .csv para .rds para facilitar a leitura pelo aplicativo do Shiny. O comando que você precisa basicamente seria o seguinte:

    saveRDS(object, file = “my_data.rds”)

    Segue o link de referência: http://www.sthda.com/english/wiki/saving-data-into-r-data-format-rds-and-rdata

    O arquivo “global.R” faz referência a este arquivo .rds no script para o aplicativo do Shiny conseguir enxergar os dados.

    Obrigado pelo comentário.

    Abraços!

  3. Entao Marcos estou com alguns problemas :/, eu salvei como RDS como vc me falou, segue a print: https://i.imgur.com/8JIzGGC.jpg tentei salvar o Pg tbm em vez do retorno da função, mas quando eu rodo o app shiny ele da esse erro: https://i.imgur.com/2H16Np2.jpg. Segue a print de importação do globao shiny: https://i.imgur.com/8VAV9jA.jpg Posso subir no github caso vc queira ver o codigo todo, só me dar um toque que posto o link do github aqui. Muito obrigado mesmo pela ajuda e pelo tutorial =)

    • Eu tentei gerar uma pag web standalone pelo prorpio Rstudio, mas to sofrendo com o erro pandoc.exe out of memory e parece ser bem recorrente no windows da galera.

    • Wesley,

      Acredito que o seu erro possa estar acontecendo na referência onde estão seus dados, você precisa no script referenciar uma pasta existente que será publicada, e não um arquivo no seu diretório local. Por exemplo, no meu caso coloquei o arquivo .rds dentro da pasta “data” e publiquei esta pasta quando gerei a aplicação no Shiny. Por isso meu comando ficou assim:

      brasileiropg <- readRDS(file = "data/brasileiropg.rds")

      De repente se você colocar o arquivo .rds dentro de uma pasta e lembrar de marcar essa pasta no momento da publicação você conseguirá resolver o problema.

  4. Pingback: Mapa com o Número de CNPJs e Empresas Limitadas no Brasil | Campo de ArrozCampo de Arroz

  5. Parabéns pelo post.

    Mesmo sendo um pouco leigo no assunto consegui reproduzir o mapa.

    Agora surgiu uma dúvida. Tem como gerar PDF do arquivo (ou .png, sem fundo, com alguma qualidade gráfica) para ser utilizado em LaTEx?

    O arquivo que gera em png/jpeg não tem boa qualidade e quando imprimimos o documento aparece algumas linhas horizontais transparentes.

    Como dito, sou leigo no assunto.

    Grato pela atenção

    • Olá Charles!

      Parabéns por ter conseguido reproduzir o mapa! São muitos detalhes e nem sempre é fácil para que está começando.
      Sobre a sua pergunta, o R tem uma função de exportação para PDF – o comando seria o seguinte:

      pdf(file.pdf,width=6,height=4,paper=’special’)

      Porém eu testei e este comando só funciona para “plots” tradicionais. Como este mapa usa a library “leaflet” a forma de exportação é mais complicada, precisa instalar um plugin, como mostra o link abaixo:

      https://stackoverflow.com/questions/24056794/convert-leaflet-map-snippet-to-image

      De repente lendo e entendendo o funcionamento do plugin você consegue utilizá-lo.

      • Obrigado pela dica Marcos,
        Eu até consegui exportar, mas o problema de aparecer algumas linhas contínuas horizontais que cortam o mapa quando se imprime persiste. O motivo, acho eu, pode ser o plano de fundo, pois ainda não consegui deixa-lo transparente.
        Como não sou da área estou aprendendo com trabalhos como o seu, assim, aproveito o ensejo para parabeniza-lo novamente. abs!

  6. Parabéns Marcos pelo trabalho e pela iniciativa de repassar seu conhecimento. Repliquei seu exemplo usando qtde de consultas apenas nos municípios de MG e deu certo. Porém, gostaria de acrescentar algumas informações:
    1) Colocar o título do gráfico na parte superior do mapa (ou se possível, desmontar como faço para movimentá-lo).
    2) Inserir uma legenda com as escalas de cores, por exemplo (de 0 a 500 consultas um tom claro de azul; de 501 a 1000 consultas um tom mais escuro de azul e etc)
    3) Como o meu interesse é apenas nos municípios de MG, seria possível aparecer, no resultado, apenas o mapa de MG ao invés de todo o mapa mundial?
    Desde já agradeço mais uma vez a ajuda!

    • Olá Bruno, tudo bem? Que bom que conseguiu reproduzir.
      Sobre as sugestões que você deu, todas são possíveis, tem só que dar uma lida na documentação da biblioteca Leaflet para entender quais comandos adicionar. Sobre deixar somente o estado de MG, acredito que você conseguirá fazer isso tranquilamente encontrando um shapefile que só tenha o estado de Minas Gerais. No próprio site do IBGE deve ter.

  7. Boa tarde, meu jovem. Excelente trabalho. Estou seguindo desde já.

    Uma dúvida. Por um procedimento similar a este da postagem, é possível separar os dados vetoriais somente para um estado e, mais especificamente, para um conjunto de municípios?! Pretendo fazer uma mapa sobre desmatamento apenas entre municípios da Amazônia legal maranhense. Qual seria o caminho?

    Att.

  8. Olá Marcos,
    Parabéns pelo post!!!

    Dúvida estou inserindo o mapa no RMarkdown + Flex Dashboard, mas não está aparecendo, neste caso terei que converter os arquivos em (rds.)?

    Obrigado!

Deixar mensagem para Marcos Vinicius Fontes Cancelar resposta