NO EPICENTRO

Como fizemos o mapa interativo que te coloca no epicentro da epidemia de Covid-19 no Brasil

Projeto feito em parceria pela Agência Lupa e Google News Initiative mostra o que aconteceria caso todos os mortos da Covid-19 no país fossem seus vizinhos. Veja como ele saiu papel

Rodrigo Menegat Schuinski
datavizbr
Published in
30 min readJul 24, 2020

--

por Rodrigo Menegat, Tiago Maranhão e Vinicius Sueiro

Se todos os mortos pela Covid-19 no Brasil fossem seus vizinhos, seu bairro provavelmente desapareceria do mapa. É possível que até a sua cidade inteira sumisse.

Imaginar esse cenário hipotético pode ajudar a entender o tamanho da crise sanitária que afeta o país, mas visualizar sua vizinhança deserta de uma semana para a outra não é simples. A ideia vem fácil à cabeça, ainda que de forma abstrata. A imagem, não.

Uma parceria entre o Google News Initiative e a Agência Lupa mostra na prática como seria essa realidade. Usando a localização do usuário, dados do Censo de 2010 e mapas de rua, esta reportagem interativa mostra qual seria o raio da devastação caso o epicentro da epidemia no Brasil fosse a casa do leitor.

Além dos três pares de mãos que escreveram esse texto, o projeto envolveu mais quatro profissionais em funções de edição e direção criativa: Alberto Cairo e Marco Túlio Pires, pelo Google, e Natália Leal e Gilberto Scofield Jr., pela Lupa.

O trabalho de todos foi motivado pela convicção de que, ao colocar o público no núcleo da doença, ainda que de forma hipotética, seria possível mostrar de forma mais clara a dimensão do problema.

Mas por que pensamos assim e como executamos o projeto? Aqui, vamos explicar em detalhes como fizemos a ideia sair do papel.

Conceito

Uma tragédia invisível

No momento em que começamos a escrever esse texto, no dia 29 de junho de 2020, 58.390 brasileiros haviam morrido vítimas do novo coronavírus.

Apesar da natureza inapelável desse número, a experiência que cada um de nós — somos três jornalistas, designers e desenvolvedores que vivem em locais diferentes do Brasil — teve com a doença até aqui foi bem diversa.

Na equipe, há quem more em São Paulo, cidade que concentra a maior parte dos casos da doença no Brasil e que viveu uma quarentena rígida entre o final de março e a metade de junho.

Há quem more no Distrito Federal, onde a epidemia atacou os centros de poder e, nas primeiras semanas, se espalhou no ritmo mais rápido de todos os estados do país.

Por fim, há também quem more no interior do Paraná, em uma cidade na qual, mais de quatro meses depois do vírus ter chegado ao Brasil, apenas uma morte havia sido registrada.

Para os dois primeiros, a experiência de viver no país que se tornou o epicentro global da maior pandemia do século foi mais marcante e intensa do que para este último, que sempre viu as partes mais dramáticas da crise bem longe de sua vizinhança.

Ainda assim, mesmo quem mora no centro do caos geralmente experimenta a crise sanitária de dentro de casa, pela televisão e pela internet. A enorme dimensão das vidas perdidas não é tão palpável quanto os inconvenientes do isolamento e das ruas vazias.

A realidade, porém, independe de onde você mora ou de como vive nos dias de quarentena. Dezenas de milhares de brasileiros já morreram. Milhares morrem toda semana. Eles estão dentro de hospitais espalhados por todo o território nacional, mas não os vemos.

Esse projeto surgiu da seguinte indagação: como fazer para que as pessoas passem a enxergar esses mortos? Como fazer para que o custo humano da doença seja mais visível que horas de tédio, lojas fechadas e calçadas sem gente?

Referências familiares

60 mil pessoas mortas. É como se um Estádio do Arruda lotado, no Recife, desaparecesse. Como se dois Sambódromos do Anhembi, em São Paulo, sumissem. É impressionante, não?

Bem, certamente é impressionante para quem tem esses locais como marco cotidiano. Se você mora na capital de Pernambuco, sabe que o estádio é gigante. Mas e se você nunca chegou perto dele?

Para quem mora em Ponta Grossa, no interior do Paraná, as referências de tamanho são outras. A ideia de um sambódromo não evoca muita coisa. O estádio da cidade não é o Arruda, mas sim o Germano Krüger.

Traçar paralelos com lugares como esses faz mais sentido para o pontagrossense do que qualquer parâmetro supostamente universal.

A lógica vale para quem está em São Paulo, em Brasília ou em qualquer lugar: quanto mais familiar a unidade de medida, mais fácil compreender a dimensão da epidemia. E será que existe algo mais familiar do que o lugar em que moramos?

A ideia fundamental deste projeto é fazer com que as vítimas da Covid-19 se tornem, subitamente, íntimas do usuário.

Durante a leitura, os 60 mil mortos não são mais pessoas que vivem a milhares de quilômetros. São vizinhos e conhecidos. A referência não é mais um estádio em outro canto do país ou algum evento histórico distante. São as ruas que o leitor atravessa todos os dias. Assim, a pandemia se materializa.

Foi a partir desse conceito que planejamos a experiência, elaboramos métodos, reunimos dados e, por fim, construímos a narrativa da reportagem. Neste documento, vamos mostrar como o plano saiu do papel.

Brainstorming

Elementos básicos

Semanalmente, todos os envolvidos no projeto se reuniam para conversar. Logo no primeiro encontro, concordamos que duas características seriam essenciais para realizar o conceito exposto acima.

O mais crucial era que a experiência do usuário fosse personalizada e individualizada— ponto enfatizado desde o início por Alberto Cairo, que foi quem teve a ideia de transportar as mortes para a vizinhança do leitor.

Ao fazer com que os usuários se sentissem pessoalmente atingidos, poderíamos romper com a sensação de distância entre a vida de quem ainda não foi diretamente afetado pela doença e a realidade da quantidade crescente de mortos.

Além disso, a linguagem adotada na visualização de dados teria de ser a mais direta possível, afastando-se de abstrações excessivas.

Um gráfico que mostra a evolução da curva da doença é informativo, mas esconde qual é sua própria matéria-prima. As linhas, na verdade, são apenas a representação de um agregado de pessoas. Para evitar essa separação, a linguagem teria de ser a mais tangível possível para, assim, enfatizar a natureza dos dados.

Com essas necessidades anotadas, começamos a parte prática do trabalho fazendo aquilo que todo mundo que está em busca de criatividade faz: reunimos conteúdos que gostaríamos de “imitar” — originalidade nada mais é que se inspirar nos nomes certos.

Inspirações

Decidimos começar a busca indo atrás de metáforas visuais que dialogassem com nossa proposta editorial, de preferência aplicadas em um contexto jornalístico e informativo.

Uma das primeiras referências que nos veio à cabeça foi um projeto que o The New York Times publicou após as eleições presidenciais americanas de 2016.

No material, o mapa dos Estados Unidos desaparece de acordo com os resultados da votação. Dois países são colocados lado a lado: em um deles, só restam as terras onde Donald Trump venceu. No outro, restam apenas os domínios de Hillary Clinton.

Mapa que apaga as áreas dos Estado Unidos onde Hillary Clinton teve mais votos que Donald Trump
Mapa que apaga as áreas dos Estado Unidos onde Donald Trump teve mais votos que Hillary Clinton

A metáfora usada pelo jornal nova-iorquino é forte porque desfigura elementos familiares ao leitor, o que causa desconforto. Além disso, a representação se alinha com o conceito de nossas própria reportagem: desaparecimento, apagamento, sumiço.

Uma referência semelhante produzida no Brasil é o projeto “Aqui não mora ninguém”, feita pela Plano C, uma empresa de consultoria em dados geoespaciais.

As áreas laranja representam regiões desabitadas do Brasil

Na visualização acima, áreas do país em que não mora nem sequer uma pessoa estão pintadas de laranja. Novamente, vemos a metáfora do vazio e da ausência, mas dessa vez no mesmo espaço em que iríamos trabalhar: o território brasileiro.

Os dados mostrados em ambos os exemplos, porém, não levam em conta um aspecto importante: a densidade demográfica.

Tanto as áreas apagadas no mapa do The New York Times quanto os quadrados alaranjados no mapa da Plano C exibem valores discretos: o candidato venceu nessa região? Existe alguém morando aqui?

Como nossa preocupação era representar a quantidade total de mortes por Covid-19 no Brasil em um determinado momento, precisávamos mostrar também a quantidade de pessoas que moram em determinada área.

Sem esse elemento, há o risco de confundir um espaço grande com um espaço onde mora muita gente, o que nem sempre é verdade. Moram mais pessoas em uma quadra no centro de São Paulo do que em dezenas de quilômetros no extremo norte do país, por exemplo.

Assim, buscamos também referências em projetos que preocupam-se em enfatizar essa dimensão da geografia.

Entre as mais interessantes estavam um projeto do The Pudding que representa a quantidade de pessoas que moram em determinada área como uma barra em cima de um mapa, gerando ‘montanhas’.

Mapa de densidade populacional produzida pela empresa americana de jornalismo de dados The Pudding

O resultado é uma visão inusitada da distribuição populacional global, mais intuitiva e fácil de ler que os clássicos mapas de cor ou calor.

Outra referência importante foi um gráfico interativo publicado pelo jornal Nexo que, hoje, está inacessível por problemas técnicos na visualização.

A mesma quantidade de pessoas mora na área azul e na área vermelha

No material, o usuário informava em que cidade morava. Em seguida, ele recebia como resposta um mapa do Brasil que destacava uma série de outros municípios que, somados, têm a mesma população que a localização do leitor.

Para igualar a quantidade de pessoas que vivem em uma cidade como São Paulo, por exemplo, era necessário pintar boa parte das regiões Norte e Centro-Oeste. Assim, a distribuição desigual da povoação do território era representada de um ponto de vista bastante pessoal.

Entretanto, tanto o trabalho do The Pudding quanto o do Nexo dependem de algumas camadas de abstração. O primeiro é, na prática, um gráfico de barras com escalas implícitas. O segundo pinta polígonos com base em uma condição.

Outro item da nossa lista de inspirações representa a população de forma mais simples: cada pessoa é representada por um único ponto. Trata-se do Racial Dot Map, desenvolvido por pesquisadores da Universidade de Virgínia.

Cada ponto representa uma pessoa. Cada cor, uma raça.

A visualização de dados usa unidades censitárias para mostrar onde vivem pessoas de diferentes raças nos Estados Unidos. Cada etnia é representada por uma cor. O Nexo também produziu um mapa parecido, mas com dados brasileiros.

Além das referências de representação visual, procuramos também peças que personalizassem ao máximo a experiência de leitura. Mais duas reportagens do The New York Times serviram como exemplo de boas práticas.

A primeira fala sobre o aumento de temperatura em diversas cidades do planeta, sempre iniciando a narrativa a partir do local onde está o leitor.

Gráfico personalizado mostra o crescimento da temperatura na cidade natal do leitor

A segunda usa uma estratégia semelhante para falar de poluição atmosférica.

A quantidade de micropartículas de poluição no ar da cidade onde o usuário mora é representada por pequenos círculos

Por fim, também procuramos nos cercar de histórias e imagens com forte impacto estético e emocional.

Entre elas, estavam as foto de covas rasas que estamparam a capa de muitos jornais durante o auge da epidemia em Manaus e em São Paulo. O número de túmulos poderia servir de indicador sobre a evolução da epidemia, com um forte e mórbido apelo visual.

Covas abertas em São Paulo. Foto: José Antonio de Moraes/Anadolu Agency/Getty

Homenagens e listas de nomes como o Memorial Inumeráveis também foram importantes no processo.

Projeto reúne obituários de vítimas da Covid-19 no Brasil

A iniciativa reúne pequenos obituários para alguns dos mortos, relembrando que cada item das contagens de vítimas não era só um número, mas uma pessoa única e insubstituível.

A lista acima, claro, não é exaustiva: estão ali apenas as inspirações que listamos formalmente.

Em bate-papos informais, citamos muito mais conteúdos. Foi a partir desse sem-número de influências que conseguimos refinar nosso conceito inicial.

Ideação

Depois que a lista de referências ficou pronta, era a hora de usá-la como fermento para nossas próprias ideias e, então, chacoalhar a massa até que surgisse algo novo e interessante.

Já sabíamos que, em linhas gerais, nossa tarefa seria mostrar a distribuição de mortes por Covid-19 ao redor do usuário. Entretanto, há várias maneiras de executar essa proposta.

Para escolher a melhor forma de contar a história, decidimos criar um estoque de ideias e só depois escolher a melhor entre elas.

Assim, listamos onze propostas. Várias eram bastante parecidas entre si, com diferenças apenas nos métodos ou na representação visual. Outras tentavam ser tão criativas que até fugiam do conceito original. Todas elas estão listadas no quadro abaixo.

Esboço que lista onze projetos que consideramos antes de escolher o formato final

Esses garranchos são difíceis de entender — algumas semanas depois que esses desenhos foram feitos, até mesmo nós precisamos nos esforçar para lembrar exatamente o que cada item significava.

Para ajudar a desvendar os rabiscos, segue abaixo a lista de ideias que consideramos, com algumas explicações complementares.

  1. A ideia era desenhar um círculo ao redor de coordenadas geográficas informadas pelo usuário. O tamanho do raio seria calculado usando uma estimativa da densidade demográfica da região, que também seria usada para preencher a área com pontos.
  2. Trata-se do mesmo que a proposta anterior, mas enfatizando a relação entre casos e mortes. O círculo referente aos casos seria muito grande, devorando cidades inteiras e revelando que a doença é muito mais comum do que parece.
  3. Em vez de nos preocuparmos com a densidade demográfica da região em torno do usuário, nessa proposta iríamos transformar todo o terreno em um cemitério denso. Assim, ele teria o mesmo tamanho independentemente da localização do usuário.
  4. A proposta era encontrar áreas grandes e conhecidas próximas ao leitor, como parques e praças, e preenchê-las com covas o bastante para enterrar todos os mortos da epidemia no país.
  5. Ideia semelhante ao item 1, mas em que, em vez de gerar um círculo perfeito, simplesmente somaríamos a população dos setores censitários (calma, logo vamos explicar melhor o que isso significa) adjacentes.
  6. Praticamente o mesmo que a proposta anterior, mas com outra fonte de dados: a grade estatística do IBGE. Vamos explicar melhor os detalhes depois, mas o método faria o mapa ficar com uma aparência quadriculada.
  7. Aqui a ideia é apagar do mapa várias cidades próximas ao usuário cujo número de habitantes é menor que o total de mortos por Covid-19 no Brasil.
  8. Outra proposta parecida com a número 1, mas dessa vez um mapa 3D com mais detalhes sobre as áreas e construções afetadas em vez de um simples mapa de ruas.
  9. Desdobramento da ideia número 8, esse mapa mostraria de forma ainda mais detalhada os edifícios da cidade do usuário.
  10. Mais fora da caixa e pretensamente artística, essa proposta usaria realidade aumentada para mostrar uma ‘lágrima’ para cada pessoa morta pela doença na tela do leitor.
  11. Na tentativa de combinar a originalidade da proposta 10 e as referências geográficas individualizadas de todas as demais, essa proposta mostraria na câmera do celular do leitor como os entornos teriam sido afetados pela epidemia.

Com essa lista, dá para perceber que nossa imaginação foi longe, mas que mesmo assim batemos o martelo em uma proposta próxima do conceito original e bem mais pés-no-chão. Por quê?

Os critérios para a escolha foram disponibilidade de dados, viabilidade técnica, estética agradável e a possibilidade de enviar uma mensagem que fizesse sentido para o maior número possível de pessoas.

Como cada uma das propostas que rabiscamos se saiu nesses quesitos, afinal? Vamos analisar item por item.

As propostas que envolviam realidade aumentada seriam difíceis de executar com uma equipe pequena e em pouco tempo.

Aquelas que dependiam de modelos 3D só seriam interessantes para as poucas cidades do país com muitos prédios altos.

A proposta de transformar espaços públicos em cemitérios dependeria de que espaços grandes o suficiente existissem perto do usuário, o que poderia não acontecer em regiões afastadas dos maiores centros urbanos.

Distribuir covas ao redor do leitor minimizaria a personalização da experiência, uma vez que o resultado seria semelhante para todos, independentemente das características da região.

Restaram, portanto, os itens 1, 2, 3 e 4. No final das contas, não escolhemos apenas uma ideia para trabalhar: o produto final foi construído com elementos de todas essas.

Roteiro

Depois de jogar as ideias na mesa, decidimos que o melhor caminho seria preencher a vizinhança do usuário com as mortes da Covid-19 no país.

Entretanto, o material não poderia se resumir a isso. Ainda que esse elemento interativo fosse cativante por si só, a reportagem precisava de uma narrativa de verdade.

Contar uma história, encadear ideias e evocar uma sequência de imagens é essencial para que um conteúdo seja memorável. Sem isso, iríamos apenas fazer com que o usuário apertasse botões e visse animações bonitas. Algo assim seria um brinquedo virtual empolgante, mas que informa pouco.

Assim, uma preocupação central do projeto foi oferecer mais que um objeto digital brilhante e divertido. Queríamos desenvolver uma estrutura narrativa capaz de deixar marcas.

É verdade que começamos a exposição do ponto de vista mais particular possível, literalmente em cima da casa do usuário. Entretanto, conforme a reportagem avança, nos afastamos gradualmente desse ponto de vista centrado no umbigo do leitor.

Primeiro, passamos para uma cidade vizinha que sumiria do mapa.

Depois, visitamos uma capital próxima.

Para terminar, lembramos que na verdade os mortos não estão espalhados ao redor da casa de quem está lendo, mas que são reais mesmo assim.

Sem perceber, elaboramos uma estrutura que evoca as dinâmicas informativas que a pesquisadora americana Nikki Usher chama de near view e far view.

No livro Interactive Journalism, de 2016, ela afirma que uma das possibilidades abertas pelo jornalismo de dados é oferecer tanto uma visão personalizada e próxima ao leitor quanto uma visão ampla, que revela como um assunto afeta a sociedade como um todo.

Dois pontos de entrada narrativa diferentes contam a história de uma forma organizada que oferece tanto experiência quanto contexto social; perto e longe. A prática de contar a história de perto e de longe dá a capacidade de as histórias ressoarem através de uma paisagem social mais ampla e dentro do próprio quintal do usuário

Nikki Usher, em Interactive Journalism (2016), pg. 161

Em suma, foi isso que tentamos fazer: contar uma história que começa no quintal do usuário, mas que revela uma paisagem social ampla.

Mão na massa

Agora já sabíamos o que queríamos construir, mas ainda não tínhamos certeza de como o faríamos.

Depois de algum bate-cabeça, notamos que a melhor forma de decidir era sujando as mãos. Assim, começamos a fazer testes para descobrir na prática o que funcionaria melhor.

De acordo com os resultados alcançados em pequenos protótipos, poderíamos tomar uma decisão informada e só então passar para o projeto em escala real, com todas as complexidades envolvidas.

A primeira coisa a escolher não poderia ser outra: qual fonte de dados usar.

Distribuição populacional

A base de dados mais crítica do projeto seria a representação da distribuição populacional do Brasil. É a partir dela que todos os cálculos seriam feitos. Podíamos escolher entre duas opções para tal, ambas produzidas pelo IBGE.

A mais detalhada é a grade estatística, que foi usada em um dos projetos que listamos como referência: o mapa “Aqui não mora ninguém” da consultoria Plano C.

Trata-se de uma divisão do território brasileiro em uma série de retângulos com 200 m² em zonas urbanas e 1 km² em zonas rurais, sem obedecer a limites administrativos como estados ou municípios. Os dados informam quantas pessoas moram em cada um desses polígonos.

Cada retângulo na imagem acima é um item da grade estatística do IBGE. Quanto mais escuro, mais pessoas moram naquela área.

A outra alternativa eram os setores censitários, divisões territoriais feitas para organizar o Censo de 2010. Elas têm tamanhos diversos e respeitam os limites das cidades e estados, ao contrário da alternativa anterior.

Apesar de serem menos granulares, os setores trazem informações mais densas. Além da quantidade de pessoas que moram em cada polígono, sabemos também a idade de cada uma delas e a renda média dos habitantes, por exemplo.

Os setores censitários costumam ser menores em áreas muito povoadas e maiores em áreas com menor densidade demográfica.

De início, pensamos em usar o dado mais detalhado possível. Assim, fizemos alguns testes com a grade estatística. Entretanto, logo aparecem problemas.

Eram muitos arquivos pesados, o que dificultava o processamento. A base completa tem 13,5 milhões de polígonos, itens demais para computar de forma ágil.

A execução do script tinha de levar no máximo 3s, na pior das hipóteses. Mais do que isso e o site demoraria demais pra carregar — e não há nada que fruste mais os leitores do que uma página lenta. Assim, passamos aos testes com setores censitários.

Ainda que a base geográfica do Censo 2010 seja grande, ela divide o país em bem menos pedaços: cerca de 350 mil. Com isso a complexidade da computação diminuía por uma ordem de grandeza.

Além disso, dois de nós já tinham experiência com setores censitários. Em 2018, havíamos publicado uma reportagem que cruzou essas informações demográficas com dados eleitorais.

Uma das opções, portanto, era mais fácil de trabalhar e, ainda por cima, era uma velha conhecida. A decisão estava tomada.

As mortes

A segunda base de dados necessária para fazer o aplicativo funcionar deveria, em tese, ser bastante simples: precisávamos da contagem de mortos por Covid-19 no Brasil. Entretanto, a divulgação desses números pelas autoridades públicas tem sido confusa desde o início da epidemia.

Nas primeiras semanas, ela acontecia de forma errática e pouco granular. Mais recentemente, mudanças metodológicas corroeram a confiança nas informações oficiais do Ministério da Saúde.

Para contornar a falta de acesso aos números, diversas entidades independentes coletam e publicam as próprias estatísticas. Assim, precisávamos escolher mais uma vez qual fonte usar.

As opções eram várias: dados divulgados pelo Conselho Nacional de Secretários de Saúde (CONASS), números reunidos por um consórcio de veículos de imprensa ou ainda estatísticas publicadas por jornalistas e pesquisadores independentes, como o Lagom Data ou o Brasil.io.

O essencial aqui era que a base fosse publicada em um formato consistente, de forma contínua e de fácil acesso. De novo, fizemos uma avaliação individual das opções disponíveis.

Os dados do CONASS e do consórcio de veículos de imprensa não são publicados em formato acessível.

O Lagom Data divulga os números em formato aberto, mas através de um link para download e não de um sistema de API, saída que facilitaria nosso trabalho de coleta.

Por eliminação, restou o Brasil.io. Com um time de cerca de 40 voluntários, a equipe liderada pelo desenvolvedor Álvaro Justen compila casos e mortes diários em cada cidade do país desde março.

Além disso, o projeto está sob licenças GNU e Creative Commons, o que permite a reprodução do conteúdo. Esses valores são próximos dos princípios que adotamos para esse projeto, que também é de código-aberto e tenta ao máximo ser replicável.

Com mapas e o número de mortes em mãos, restava desenvolver uma fórmula para calcular as áreas que destacaríamos em volta de cada usuário.

A partir de agora, vamos entrar em detalhes sobre o que o aplicativo faz por trás das cortinas.

Atrás das cortinas

Na prática, apenas um dos elementos previstos no roteiro era difícil de desenvolver: o cálculo da área em torno do usuário. Uma vez pronta, essa função também serviria para simular os efeitos da doença nas capitais estaduais.

O restante da narrativa envolvia operações triviais: descobrir a cidade mais próxima que sumiria do mapa, por exemplo, é algo que se resolveu com um par de filtros.

Calcular a região de destaque, porém, seria computacionalmente complexo. Com isso, questões técnicas deram as caras: que linguagem de programação usar? Como garantir que a execução seja a mais rápida possível? Como fazer para desenvolver uma solução eficiente em poucas semanas?

Por questão de familiaridade, decidimos usar o Python para desenvolver o back-end do projeto. A linguagem não é a mais veloz do mundo, mas compensa a lentidão com flexibilidade e uma série de módulos úteis.

A maior parte das computações usa o pacote de análise geo-espacial GeoPandas e outras bibliotecas relacionadas, como o Shapely.

As tecnologias usadas, porém, eram uma preocupação secundária. Antes de escrever o código, precisávamos definir um algoritmo — ou seja, um passo-a-passo detalhado dos cálculos.

Algoritmo: plano A

Primeiro, tentamos uma abordagem que se baseava em selecionar polígonos adjacentes até atingir a população necessária. Os passos eram os seguintes:

  • De posse das coordenadas geográficas enviadas pelo usuário, descobrir em qual setor censitário ele se encontra
  • Depois, selecionar os setores censitários vizinhos e checar se eles têm a população necessária
  • Caso contrário, selecionar os vizinhos dos vizinhos, e assim sucessivamente
Representação visual do algoritmo: de vizinho em vizinho, tentávamos chegar ao total de mortos

Depois de implementar essa solução e testar o programa com algumas coordenadas de exemplo, percebemos um problema.

Ainda que a performance fosse rápida e a lógica simples de entender, o resultado era uma série de áreas amorfas. As figuras pareciam arbitrárias e não faziam sentido para alguém que não estivesse por dentro do método de cálculo.

Resultado do algoritmo no bairro da Barra Funda, em São Paulo: como explicar para o leitor qual é o sentido dessa área vermelha estranha?

Explicar como chegamos aos contornos exibidos seria uma tarefa difícil, comprometendo a eficácia da mensagem. Assim, passamos para uma segunda alternativa.

Algoritmo: plano B

Agora sabíamos que o resultado final dos cálculos precisava ser uma forma imediatamente compreensível. Percebemos também que a ideia de colocar o usuário no centro da epidemia sugeria uma forma específica: um círculo ao redor da localização do leitor.

Dessa forma, deixamos de lado (por enquanto!) as preocupações com complexidade computacional, elegância de código e performance. Primeiro, calcularíamos o raio, da forma que fosse. Depois, otimizaríamos o programa, se necessário.

Resumidamente, os passos para o novo cálculo eram os seguintes:

  • Colocar um ponto no mapa, representando as coordenadas exatas do usuário
  • Aumentar o raio do ponto e descobrir quais setores censitários cruzam esse novo círculo
  • Adicionar a população de cada setor censitário de acordo com o percentual de interseção. Caso um setor censitário com 100 moradores estivesse 100% dentro do círculo, por exemplo, incluiríamos as 100 pessoas no total. Caso estivesse 30% dentro, contaríamos apenas 30
  • Se o número de pessoas dentro do círculo estiver entre 90% e 110% do total de mortos por Covid-19 no Brasil, terminar o cálculo
  • Se a população dentro do círculo for menor que o total de mortos no país, aumentar o raio do círculo e repetir os cálculos
  • Se a população dentro do círculo for maior que o total de mortos, reduzir o raio do círculo e repetir os cálculos

Ainda que seja mais complexo que o anterior, esse método gerou resultados mais fáceis de entender. Os casos de Covid-19 não se espalhavam mais de forma arbitrária, mas em direções uniformes ao redor do usuário.

O raio de mortes a partir do Centro Histórico de Recife. O formato circular passa a mensagem de forma mais efetiva do que no exemplo anterior.

Entretanto, o resultado agradável veio com um preço: o tempo de execução era muito maior. Agora o desafio era fazer o script rodar rápido o bastante para alimentar uma aplicação online.

Desafios de performance

Já tínhamos estimado que o tempo máximo aceitável para fazer o cálculo era de três segundos. Com uma demora maior, cansaríamos o usuário. Quem aguenta esperar três segundos para um conteúdo carregar hoje em dia, afinal?

No formato inicial, sem otimização alguma e desenvolvido sem preocupação com performance, o programa levava dez vezes mais do que isso. Depois de alguns testes, identificamos os principais gargalos. Eram os seguintes, em ordem de morosidade:

  1. Carregar todos os setores censitários na memória
  2. Calcular o percentual de interseção entre cada setor censitário e o raio do círculo
  3. Descobrir quais setores censitários faziam interseção com o círculo

Foi aí que uma trinca de módulos do Python salvou nossa pele: Feather, Rtree e PyGEOS. Todos eles expandem e otimizam as funcionalidades do Geopandas. Além disso, tivemos de pré-processar a base de setores censitários.

Mas como exatamente essas ferramentas nos ajudaram e que tipo de pré-processamento foi necessário? Vejamos, item por item:

1. O Brasil está dividido em mais de 300 mil setores censitários. Entretanto, só precisávamos dos poucos setores que estão perto da localização de cada usuário. Assim, tivemos de encontrar uma forma de carregar apenas os dados que nos interessavam.

Para fazer isso, dividimos o território brasileiro em 10 mil retângulos e salvamos cada um deles, com seus respectivos setores, em um arquivo diferente.

Com isso, pudemos ler apenas o retângulo que continha o ponto informado pelo usuário — ou também os retângulos vizinhos, caso ali não houvesse população suficiente.

Essa estratégia já reduziu significativamente o tempo de carregamento, mas havia um jeito de deixar o processo ainda mais rápido. Em vez de usar arquivos no formato shapefile, como fornecidos pelo IBGE, usamos arquivo no formato feather, que foi criado especialmente para agilizar as operações de leitura.

Comparação entre o tempo necessário para ler um arquivo no formato shapefile e no formato feather: o último é quase três vezes mais rápido.

2. Para computar quantas pessoas moram dentro de um determinado raio, é necessário calcular a interseção entre cada setor censitário e a área do círculo. Usualmente, o GeoPandas usa um pacote de nível mais baixo chamado Shapely para fazer esse tipo de operação.

O problema é que o Shapely não é rápido para processar centenas de polígonos de uma vez, já que não trabalha com operações vetorizadas. Essas operações são o que fazem pacotes estatísticos executarem código rápido.

Entretanto, existe um pacote chamado PyGeos que, embora menos flexível, usa vetores para fazer o mesmo que o Shapely.

A versão mais recente do GeoPandas inclui suporte opcional para essas funções. Assim, com uma linha de código a mais, a velocidade de execução do programa aumentou ainda mais.

gpd.options.use_pygeos = True

3. Por fim, restava descobrir como calcular de forma mais rápida quais eram os setores censitários que faziam interseção com o círculo.

A solução para isso veio de um velho conceito da análise geoespacial, mas que não conhecíamos ainda: os índices espaciais, ou spatial indexes, que são implementados no GeoPandas através do pacote Rtree.

O conceito se parece um pouco com a solução que encontramos para o item 1: na prática, são poucos os setores censitários que tocam o círculo. Qual é o sentido de computar todos esses polígonos, até mesmo aqueles que estão muito distantes?

Ao usar um spatial index, evitamos esse trabalho desnecessário. Em vez de verificar individualmente se cada um dos elementos encosta no círculo, podemos primeiro criar ‘envelopes’ ao redor de pequenos grupos de setores.

Um tipo específico de índice espacial chamado r-tree. Veja como os polígonos menores, vermelhos, são encapsulados por polígonos maiores

Esses envelopes atuam como filtros prévios: primeiro, verificamos quais deles tocam na circunferência. Caso algum não encoste, podemos ignorar todos os setores censitários que estão lá dentro: logicamente, nenhum deles vai interceptar o círculo.

Assim, é possível descartar boa parte das entradas de antemão e processar apenas aquelas que importam.

Com todas essas ferramentas juntas, conseguimos alcançar um desempenho bom o bastante para todas as zonas urbanas do país.

Depois de toda a otimização, o tempo de execução do código caiu de meio minuto para menos de três segundos

Na frente das cortinas

Com o tamanho do raio calculado a partir da localização do usuário, já poderíamos posicionar o leitor em um mapa e desenhar o círculo.

O próximo desafio era visualizar cada um das dezenas de milhares de habitantes dessa área como pontos no mapa, algo potencialmente complicado porque a quantidade de mortes, infelizmente, ainda aumenta a cada dia.

Além disso, os pontos teriam que ser desenhados ao redor de onde quer que fosse a localização do usuário, respeitando a população dos setores censitários interceptados pelo círculo. Por fim, ainda precisávamos evitar que eles fossem apresentados em lugares como ruas, parques e lagos.

Já que nenhum de nós possuía muita experiência com visualizações de dados em mapas, não sabíamos de antemão que caminho tomar. Assim, como em todas as fases do projeto, consideramos uma série de saídas diferentes antes de chegar ao produto final.

Poderíamos, por exemplo, desenhar um mapa básico usando pacotes como o D3.js ou usar uma imagem estática de um mapa pronto — saídas mas fáceis de executar, mas que pareciam pouco para um projeto ambicioso como esse.

Assim, decidimos criar um “slippy map”, ou seja, um mapa com o qual o usuário pode interagir usando zoom ou arrastando a tela para o lado, por exemplo. Entretanto, mesmo com essa decisão, restavam mais dúvidas.

Poderíamos escolher entre uma série de serviços como Mapbox, Leaflet ou Google Maps. Seja qual fosse a ferramenta escolhida, precisávamos ainda decidir como implementar as camadas adicionais para desenhar o círculo, os pontos e quaisquer outros elementos visuais — o que, por sua vez, poderia ser feito usando SVG, Canvas ou alguma funcionalidade do próprio serviço de mapas escolhido.

Decidir como implementar a interface visual do projeto não foi simples

A tarefa de escolher como prosseguir nessa área caiu nas mãos de Tiago, o engenheiro do time — e, naturalmente, ele tomou as decisões com base em equações e provas matemáticas que o restante da equipe ainda não entende muito bem.

Estimando o círculo

Por mero acaso, Tiago havia havia assistido faz pouco tempo a uma apresentação de David Eads e Paula Friedrich, uma dupla de designers norte-americanos.

Na videoconferência, eles contavam como fizeram para construir um aplicativo que mapeia a evolução do Covid-19 no estado de Illinois. Para esse projeto, os dois usaram o Mapbox e uma biblioteca de Javascript chamada turf.js.

Uma funcionalidade interessante dessas ferramentas é a possibilidade de adicionar fontes de dados e construir camadas visuais no momento em que o usuário está usando o mapa.

Essa flexibilidade para alterar a interface no momento da execução era exatamente o que estávamos procurando. Assim, resolvemos testá-las e os resultados não poderiam ter sido melhores.

Para ilustrar, segue um exemplo de como desenhamos o círculo — cujas coordenadas, vale lembrar, já haviam sido calculadas pelo algoritmo que opera atrás das cortinas.

  1. Usamos o turf.js para calcular a distância entre as coordenadas da localização do usuário e as coordenadas de um ponto do círculo
  2. Com essa distância, novamente usando o turf.js, calculamos as dimensões de um polígono para representar o círculo
  3. Com os dados desse polígono, acrescentamos uma fonte de dados ao Mapbox e, como consequência, uma camada visual ao mapa

Assim, o círculo desenhado passa a fazer parte da própria interface: o usuário pode movimentar a tela ou alterar o zoom e a forma se adapta de modo correspondente, comportnado-se como um elemento nativo.

Assim, driblamos as preocupações de redesenhar a imagem para cada interação do leitor com o mapa, o que seria uma limitação importante caso decidíssemos usar tecnologias como SVG ou Canvas.

200 milhões de pontos

Com a representação do círculo funcionando de forma adequada, faltava solucionar a outra parte do problema: como representar os habitantes da região.

A ideia era que cada pessoa fosse simbolizada por um único elemento, como já explicamos. Assim, teríamos que exibir, no mínimo, dezenas de milhares de pontos, sempre respeitando a densidade populacional de cada setor censitário.

Em uma primeira tentativa, tentamos desenhar todos os pontos usando o próprio browser. Entretanto, a implementação era mais complicado do que parecia de início.

O turf.js é capaz de gerar pontos aleatórios dentro de um retângulo, mas não dentro de um polígono com forma irregular como as divisões territoriais do IBGE.

Assim, tivemos primeiro que calcular o bounding box — espécie de ‘envelope’ retangular que envolve um polígono —de cada setor censitário e só depois preenchê-lo com pontos. Na sequência, verificamos quais desses estavam, de fato, dentro do setor e descartamos os demais.

Entretanto, com esse método, caso gerássemos apenas um item para cada morador de uma região ficaríamos sempre com itens faltando no mapa, já que boa parte deles seria ignorada.

A solução para esse problema era estimar quantos dos pontos gerados dentro do retângulo cairiam dentro do setor censitário e quantos cairiam fora. Assim, poderíamos criar pontos a mais para compensar essa diferença.

Estávamos diante de um problema de probabilidades geométricas — e foi aí que ter um engenheiro em meio a uma equipe de jornalistas e designers fez toda a diferença.

Para entender melhor, vamos fingir que a imagem abaixo representa um setor censitário, em bege, e sua respectiva bounding-box. A área que fica fora do setor censitário está pintada de azul, portanto.

Quais as chances de o ponto vermelho cair na região azul ou na região amarela?

É bastante óbvio, mas precisamos ressaltar: existe uma chance de 50% de um ponto criado aleatoriamente fique dentro do setor. Isso acontece porque o triângulo bege cobre exatamente metade da área da caixa.

Entretanto, se gerarmos apenas dez pontos, pode ser que a distribuição deles seja diferente — ou seja, que não fiquem exatamente cinco pontos na área azul e cinco pontos na área bege.

No linguajar da probabilidade, o exemplo acima tem poucos eventos. Quando um fenômeno se repete vezes, é bem possível que a distribuição real do resultado fique bem longe da probabilidade teórica.

Quanto mais pontos gerarmos, porém, menor é a chance de que uma anomalia assim aconteça. Com a repetição dos eventos, a tendência é que o resultado fique cada vez mais perto do esperado.

É o que mostramos nas simulações abaixo, em que geramos cada vez mais itens de forma aleatória.

A ideia importante aqui é que, com uma quantidade suficiente de eventos, é possível estimar com alguma segurança quantos pontos precisamos gerar ao todo para alcançar o valor necessário de pessoas dentro de cada setor.

Isso acontece graças a Lei dos Grandes Números, teorema estatístico que garante que a média dos resultados obtidos se torna mais próxima da probabilidade teórica à medida que mais eventos ocorrem.

Como iríamos criar uma quantidade grande de pontos, conseguimos usar essa regra matemática em nosso favor. Assim, o mapa não mostra exatamente a quantidade de pessoas que moram em cada setor censitário, mas uma aproximação precisa o suficiente para todos os efeitos práticos.

Para continuar com o exemplo acima, ao gerar 2 mil pontos, podemos assumir com segurança que um número muito próximo de mil vai cair dentro da área correta. Por essa mesma lógica, para fazer com que aproxidamente 2 mil pontos fiquem dentro da área correta, é necessário criar 4 mil pontos aleatórios.

Para tentar deixar as coisas mais claras, a imagem abaixo resume como foi o processo em um setor censitário de verdade.

Note como o valor de pontos dentro do setor ficou próximo do real: de 866 pontos esperados, 862 caíram dentro.

Ao final de todas essas contas, conseguimos o seguinte resultado:

Um dos primeiros protótipos, destacando as mortes em torno de um ponto no município de Palhoça, SC

No entanto, como era de se esperar, calcular e renderizar dezenas de milhares de pontos gerados dessa maneira é bastante custoso em termos de processamento. O trabalho pesado provavelmente iria travar o navegador de muitos usuários, especialmente em dispositivos móveis e computadores mais antigos.

Assim, diante da inviabilidade de se executar a simulação e o cálculo das posições dos pontos em tempo de execução, começamos a especular alternativas. Não havia saída que não envolvesse algum tipo de pré-processamento por trás das cortinas.

O que parecia uma pedra no caminho, porém, fez uma ideia ambiciosa que já havíamos cogitado algumas vezes tornar-se mais atraente: gerar previamente e carregar no mapa uma camada com 190 milhões de pontos — um para cada pessoa que compunha a população do Brasil em 2010.

Assim, em vez de criar apenas pontos dentro do círculo, os espalhamos por todo o território nacional. O raio, agora, serve apenas como uma espécie de máscara para dar destaque aos pontos que ficavam na área afetada, como na imagem abaixo.

Protótipo de mapa com que exibe um ponto para cada habitante do Brasil, em vez de exibir apenas um ponto para cada vítima da Covid-19

Esses pontos foram processados de forma semelhante ao nosso primeiro experimento: gerados de forma aleatória dentro de bounding boxes dos setores censitários, em número suficiente para que ao final do processo o número de pontos dentro do polígono do setor fosse semelhante à sua respectiva população.

Entretanto, em vez de fazer isso a cada vez que um usuário interagisse com o mapa, o cálculo foi feito uma única vez, usando o Python. Os dados resultantes — cerca de 23 gigabytes de informações geográficas — foram convertidos para tilesets usando um programa desenvolvido pela própria equipe do Mapbox: o tippecanoe.

Na prática, isso significa que todos os pontos foram salvos como uma camada a mais no mapa, no mesmo formato que a grade de ruas, por exemplo. Com isso, eles podem ser exibidos, carregados e modificados de forma pouco dispendiosa.

No final das contas, essa montanha de dados acabou sendo processada por um notebook com 10 anos de uso. Provavelmente, o que evitou um incêndio foi esse sistema de resfriamento improvisado no desespero da madrugada:

Um cooler feito de peças de Lego evitou que esse pobre computador entrasse em combustão

Com isso as peças fundamentais para a construção do esqueleto estavam prontas — embora ainda restasse um longo e minucioso trabalho de refinamento das interações, roteiro, estética e tantos outros detalhes e desafios que fomos encontrando ao longo do projeto.

O que aprendemos?

Ao fim de um período de trabalho intenso como esse, é impossível não levar algumas lições para aplicar nas próximas empreitadas. Por mais clichê que seja, não conseguimos pensar em forma melhor de terminar esse texto do que elencando algumas dessas descobertas.

Especializar tarefas, coletivizar debates

Quando decidimos montar o time que trabalharia no projeto, tínhamos em mente que cada um de nós se dedicaria a uma área específica. Uma pessoa processaria os dados, outra faria a ferramenta funcionar e outra definiria a identidade visual do produto.

Em tese, essas são tarefas bastante compartimentadas.

Claro que no final da linha de montagem, os resultados teriam de ser reunidos em um sistema único para funcionar, tecnologicamente falando.

Entretanto, seria bem possível que cada um de nós sentasse no seu computador e só falasse com os demais para pedir que os dados fossem processados em algum formato específico ou outra minúcia do gênero.

Por sorte, nossa rotina foi bem diferente. Em reuniões periódicas por videoconferência e, principalmente, em um grupo de WhatsApp que fervilhou durante muitas madrugadas, nós conversamos constantemente sobre todas as dimensões do conteúdo.

Ainda que cada profissional tivesse as suas demandas específicas para entregar, as digitais de todos estão espalhadas em cada pedaço do material.

Assim, atingimos um ponto de equilíbrio: operamos sob uma divisão rigorosa do trabalho, mas com liberdade para fazer sugestões sobre tópicos longe de nossas respectivas responsabilidades.

A primeira metade da equação garantiu produtividade e eficiência. A segunda garantiu um estoque maior de criatividade e senso crítico.

Brainstorming eterno

O já mencionado grupo de WhatsApp também serviu como repositório de links desconexos, pensamentos pela metade e ideias mal-acabadas.

Descrevendo assim, parece que a comunicação por lá só gerou ruído, mas foi exatamente o contrário.

Em vez de confinar a busca de referências às etapas iniciais do processo criativo, esse ambiente meio caótico nos fez mergulhar em uma espécie de ideação constante.

Passaram por lá sugestões de cursos online de design e machine learning, discussões sobre uso de cor em mapas, fotos de vitrais de igreja que lembram heatmaps e até imagens de árvores secas em um deserto da Namíbia.

A mídia compartilhada no grupo de WhatsApp: referências, testes, memes, cursos e árvores secas

Toda essa confusão acabou contribuindo indiretamente para a realização do projeto. De lá saíram ideias de paleta de cores, metáforas visuais intrigantes e várias formas de apresentação de conteúdo nas quais não tínhamos pensado antes.

Aprender no processo

Por fim, descobrimos que, para tirar um projeto complexo do papel em um tempo curto, é essencial ter disposição e capacidade para aprender coisas novas muito rápido.

De novo, o WhatsApp ilustra essa ideia: o nome do grupo que críamos para conversar sobre o trabalho é “Irresponsáveis Motivados”. Por quê?

A verdade é que, ainda que tivéssemos familiaridade com muitas das áreas envolvidas no desenvolvimento de um aplicativo como esse, nós nunca havíamos trabalhado na prática com várias delas.

Como todos acumulavam as responsabilidades do projeto com empregos em tempo integral durante o dia, restavam as madrugadas — tanto para estudar quando para executar. Assumir um compromisso desse, logo percebemos, não estava entre as coisas mais responsáveis que já fizemos na vida.

Entretanto, logo desenvolvemos um trunfo para compensar tal insensatez: a capacidade de mergulhar de sopetão em um tema novo e entender o essencial em pouco tempo.

Assim, pouco importava se nunca tínhamos trabalhado com o MapBox, ouvido falar de PyGEOS ou montado uma API de aplicativo interativo. Como essas ferramentas eram necessárias para o trabalho, não restava alternativa que não fosse ler a documentação, assistir tutoriais e aprender como usar.

É provável que um desenvolvedor especializado leia nosso código-fonte e faça careta. É provável que ele tenha razão. Nossa resposta? Feito é melhor que perfeito.

--

--