Geocodificação — sem Google maps API— Parte II

Pedro Paulo dos Santos
Data Hackers
Published in
6 min readJan 29, 2021
Photo by CardMapr on Unsplash

Olá novamente! Essa é a segunda parte de uma série de geocodificação de dados com R sem Google maps API. Para você que não leu o artigo anterior clica aqui.

Pra quem leu, eu preciso destacar uns pontos:

1 — Graças as atualizações das políticas de uso do Docker Hub (que não permitem mais imagens inativas) não estão mais disponíveis as imagens do postmon e do cepnode no meu repositório.

2 — Alguns leitores me retornaram que os CEP estão registrados no OpenStreetMaps para consultas nos servidores deles. Todavia, a política de uso não permite consultas em larga escala.

Considerando que faz muito tempo desde a publicação do primeiro artigo, eu preciso atualizar algumas coisas antes de continuarmos.

É possível que quem seguiu o que foi passado anteriormente realmente tenha uma lista de endereços válidos para pesquisa, porém, a maneira com que os dados foram obtidos está longe de ser a melhor forma. A seguir eu apresento uma opção.

Funções para ajudar.

Baixar a base de dados do SIHSUS de forma manual é um trabalho muito grande (além de ser chato). Uma opção prática é criar uma função que possa fazer o download dos arquivos disponibilizados direto no servidor de FTP (File Transfer Protocol) do Datasus. Volte na tela inicial dos dados, escolha as opções de download e clique “copiar endereço de link”.

O print da minha tela.

O endereço que obtive foi esse:

ftp://ftp.datasus.gov.br/dissemin/publicos/SIHSUS/200801_/dados/RDRJ2001.dbc

Elimine a parte do “…/RDEJ2001.dbc”, cole em seu navegador o endereço e pronto! Acesso ao servidor FTP.

Repare que as siglas de nomeação dos arquivos segue o disposto na página anterior:

  • RD para guias de internação reduzidas;
  • RJ para guias de internação rejeitadas para pagamento;
  • SP para os registros dos procedimentos profissionais realizados;
  • ER para guias de internação rejeitadas que possuem o código do erro.

Agora você deve ter pensado: “bastaria fazer um loop for pela lista de arquivos que eu quiser baixar…”, certo?! E é isso mesmo, mas indo além, vou copiar a função final que eu fiz para isso. A chamada é simples assim:

Ok, agora vamos para a função em si.

Eu não publiquei em pacotes porque existem outras opções disponíveis por ai que fazem a mesma coisa (ainda que não tenha visto com Sparklyr).

A seguir tem uma função wrapper do sapply para fazer as solicitações http na API do OpenStreetMaps.

Sua base de dados geográficos em um comando. Funciona para busca de pontos ou polígonos.

A chamada da função é a seguinte:

Um serviço de mapas pra chamar de seu!

Photo by Kyle Glenn on Unsplash

Bem, chegamos nos finalmente. Se você tentou utilizar a última função direto com URL do OpenStreetMaps deve ter reparado que começou a ficar lento, retornar informações vazias ou dar erro, certo?! A política de uso dos servidores de Tiles deles deixa claro que eles mantém os servidores na base da doação por isso não é para abusar, sequer pode-se anexar apps sem a autorização prévia deles.

Mas calma, tem solução. Crie o seu servidor! O software permite isso, lembre-se de ler atentamente a licença.

Inicialmente precisaremos de um arquivo .osm da localização que se pretende montar o serviço. Vá até a o site do Geofabrik ao clicar na America do Sul e depois em Brasil, será possível escolher o mapa de uma das macroregiões brasileiras. Para esse exemplo o nosso servidor será da região Sudeste.

Fonte do arquivo .osm

Salve o arquivo e em seguida vá até o repositório do mediagis e faça um clone:

git clone https://github.com/mediagis/nominatim-docker.git

Escolha a versão que pretende usar e construa a imagem Docker (o Dockerfile da 3.4 quebra em pacotes de segurança).

cd nominatim-docker/3.5
docker build -t nominatim .

TESTE A SUA PACIÊNCIA: o comando a seguir vai descompactar o arquivo .osm em um banco de dados PostgreSQL, porém o tempo que leva para isso acontecer é muito grande.

docker run -t -v <local onde está o arquivo .osm>:/data nominatim  sh /app/init.sh /data/<nome do seu arquivo .osm>.osm.pbf postgresdata 4

O número 4 é a quantidade de cores na operação, no meu isso demorou aproximadamente 8 horas para a região sudeste.

Feito esse processo ira surgir no local onde estava o arquivo .osm uma pasta chamada postgresdata. Caso voce não tenha alterado de local essa pasta bastaria apenas executar a linha de comando a seguir para ter o seu servidor funcionando.

docker run --restart=always -p 6432:5432 -p 7070:8080 -d --name nominatim -v <local do aquivo .osm>/postgresdata:/var/lib/postgresql/11/main nominatim bash /app/start.sh

Acesse o http://localhost:7070/ e verás a seguinte page:

Pronto! servidor ativo. Agora basta utilizar como URL para a função make_tiles_query o endereço http://localhost:7070/search?q=.

Dica 1: Dê uma olhada na parte de update da base de dados, para não ter que ficar descompactando novamente a cada atualização.

Dica 2: Salve a pasta postgresdata com o nome da sua região, “sudeste” por exemplo, pois, caso descompacte mais de um .osm, todos eles poderão existir dentro da mesma pasta e só alteraria o final de linha de comando do container:

docker run --restart=always -p 6432:5432 -p 7070:8080 -d --name nominatim -v <local do aquivo .osm>/sudeste:/var/lib/postgresql/11/main nominatim bash /app/start.shoudocker run --restart=always -p 6432:5432 -p 7070:8080 -d --name nominatim -v <local do aquivo .osm>/sul:/var/lib/postgresql/11/main nominatim bash /app/start.sh

Dica 3: No Brasil existem muitos municípios com nomes dobrados ou triplicados, além de infinitos nomes de bairros e ruas iguais. Utilizar a base do Brasil inteira, além de ser muito lento e pesado, irá fazer com que você tenha que lidar com esse cenário. Ao optar por manter em macroregiões a chance disso acontecer reduz.

Selecionando e Juntando as peças.

Photo by Caleb Woods on Unsplash

Se você chegou até essa parte deve ter percebido que muitos endereços podem vir com com mais de uma opção de escolha e que o objeto virou uma monstruosa lista aninhada.

É agora que o Cientista de Dados precisa colocar em prática aquele mantra do ETL (Extract, Transform and Load).

O que eu irei apresentar a seguir é uma alternativa para extrair a localização do primeiro endereço que vier nas listas, não significa que é a melhor opção.

E a chamada da função é essa:

Geocoficação Reversa funciona?! O.o

Photo by Jack Anstey on Unsplash

Com a latitude e a longitude em mãos é possível obter informações do endereço assim:

http://localhost:7070/reverse?format=geojson&lat=<valor>&lon=<valor>

Caso não seja encontrado, um erro será retornado.

Por enquanto é só! Já é perfeitamente possível trabalhar sem API externas para converter ceps em endereços, como visto no primeiro artigo, e sem a API do Google Maps para converter endereços em dados de localização.

A motivação de todo esse trabalho é o tamanho do Dataset, que, quando grande, gera um custo de processamento elevado apenas no estágio de desenvolvimento (imaginem em produção).

Caso ele não seja grande, compensaria usar serviços profissionais como o do Google. Inclusive, vale a pena mencionar, que quando se trata de geolocalização a precisão se torna um fator importante, nesse quesito, o Google maps ainda é imbatível.

Em momento nenhum eu inseri informações sobre o número das casas, pois a fonte escolhida só fornece o CEP para localização da rua, entretanto, a lógica aplicada seria a mesma, bastaria inserir mais uma referência geográfica na função make_tiles_query.

Espero que tenha ajudado. Abaixo estão meus contatos, sintam-se a vontade de me procurar em casos de dúvidas, responderei com prazer.

Github: https://github.com/dr2pedro

Linkedin: https://www.linkedin.com/in/pedro-paulo-teixeira-dos-santos-75b81b199/

Lattes: http://lattes.cnpq.br/7722439455514062

--

--

Pedro Paulo dos Santos
Data Hackers

M.S. Science, PgD. in Patient Safety, Family Health and BDent, working as Data Science.