Motion Chart no Python

Sempre é um grande desafio escolher a melhor visualização para seus dados. Seja pelo tipo do gráfico, pela paleta de cores, sobre qual recorte temporal ou regional dar nos dados, ou sobre quais variáveis vão compor a visualização, sempre paira uma dúvida sobre a melhor escolha.
Imagina ter que representar mais de 3 variáveis em um mesmo gráfico, sendo que uma delas é o tempo. Um grade desafio, não é mesmo?
Por exemplo, como representar a evolução da prevalência (total de casos por 100 mil habitantes) e mortalidade (total de mortes por 100 mil habitantes) por Covid-19 entre os Estados do Brasil, de todas as regiões do Brasil, de forma diária ao longo dos 2 primeiros anos de pandemia no Brasil?
Veja, nesse exemplo, você tem prevalência, mortalidade, data, região do Brasil e unidade da federação. São 5 dimensões em um mesmo gráfico. É possível? Na imagem abaixo, conseguimos representar os dados em determinado dia (23 de fevereiro de 2022):

Mas, com a imagem estática a dimensão tempo foi paralisada em uma determinada data, porém, se for um vídeo ou um GIF, é possível ver a evolução das prevalências e mortalidade das unidades da federação do Brasil ao longo das datas. Veja o vídeo abaixo:
Muito interessante não é mesmo? Quer aprender como construir esse gráfico animado utilizando o Python? Eu sabia que sim! Então continua lendo o post, pois nos parágrafos a seguir, você vai ter todos os detalhes de como construir esse motion chart com os dados da Covid-19 no Brasil utilizando a biblioteca Plotly do Python.
Em 25 de Fevereiro de 2020 foi registrado o primeiro caso de Covid-19 no Brasil, no Estado de São Paulo. Em 05 de Março deste mesmo ano foi confirmado um caso no Rio de Janeiro, e no dia seguinte – 06 de março – foram confirmados casos na Bahia e Espirito Santo. Em 11 de Março de 2020 a Organização Mundial de Saúde decretou Pandemia de Covid-19 e em 17 de março foi registrado o primeiro óbito no Brasil no estado de São Paulo. Somente quase 1 ano depois do primeiro caso registrado, iniciou-se a vacinação no Brasil.
Na data da escrita deste post, o Brasil já havia vivido 4 ondas de Covid-19, sendo registrados mais de 34 milhões de casos e quase 700 mil óbitos devido a complicações do Covid-19, de acordo com o site do Ministério da Saúde (https://covid.saude.gov.br/).
Para este post, foi utilizada a série diária do total de casos por 100 mil habitantes (totalCases_per_100k_inhabitants) e o total de mortes por 100 mil habitantes (deaths_per_100k_inhabitants) nos dois primeiros anos da pandemia.
O conjunto de dados utilizado neste artigo é oriundo dos registros de casos e mortes por Covid19, divulgados pelas Secretarias Estaduais de Saúde e do Ministério da Saúde do Brasil, foi sistematizado pelo pesquisador Wesley Cota e disponibilizado, com atualização diária, em sua página no Github (https://github.com/wcota/covid19br/). E foi ajustado e disponibilizado em um arquivo no formato *.csv – separado por ‘,’ – em um repositório de dados abertos que mantenho em meu GitHub – jonates/opendata.
Agora, vamos enfim, por a mão na massa.
Primeiro, acesse o Google Colab e crie um novo notebook.
Para carregar e fazer transformações no conjunto de dados, vamos utilizar a biblioteca Pandas. Portanto, precisamos importá-la:
# Importando bibliotecas necessárias
import pandas as pd
Em seguida, é preciso Carregar o conjunto de dados no Python. Para tanto utilizamos o read_csv do pandas:
# Importando o conjunto de dados
covid = pd.read_csv(
filepath_or_buffer = 'https://raw.githubusercontent.com/jonates/opendata/master/covid19_brasil/cases-brazil-states.csv',
sep=',',
decimal='.'
)
Pronto! Vamos dar uma espiadinha no conjunto de dados, bem como em sua estrutura:
# Espiando o conjunto de dados
covid.head()

# Espiando a estrutura do conjunto de dados
covid.info()

Perceba que a variável ‘date’ é do tipo object e precisamos transformar para o tipo datetime:
# Transformando o atributo 'date' em datetime (e salvando no atributo data)
covid['data'] = pd.to_datetime(covid['date'], infer_datetime_format=True)
Também, neste conjunto de dados tem o nome da unidades da federação ‘state‘ mas não tem um atributo sobre a qual das cinco regiões do Brasil pertence cada um destes Estados. Portanto, vamos utilizar um conjunto de dados disponível no GitHub que tem informações sobre geoinformações das Unidades da Federação do Brasil que tem essa informação de grandes regiões:
# Carregando arquivo com geoinformação
geoinformacao = pd.read_csv(
filepath_or_buffer = 'https://raw.githubusercontent.com/jonates/opendata/master/codigos_IBGE_UF_Regioes/codigos_IBGE_UF_Regioes.csv',
sep=';',
encoding = 'latin-1'
)
# espiando o dataframe de geoinformação
geoinformacao.head(2)

Agora vamos juntar o dataframe com informações do Covid-19 com o arquivo de geoinformação:
# Trazendo geoinformações para o dataset de covid-19
covid = pd.merge(
left = covid,
right = geoinformacao,
how = 'left',
left_on = 'state',
right_on = 'Sigla_UF'
)
# Verificando a nova estrutura do dataset
covid.info()

Pronto! Agora já temos no dataframe todas as informações necessárias para elaboração do motion chart. Porém, como os registros de óbitos e casos em todos os estados do Brasil existem somente após maio de 2020, vamos filtrar a base de dados depois desta data para que todas as Unidades da Federação apareçam no gráfico animado. Também, vamos retirar os resultados agregados do Brasil e deixar somente os das Unidades da Federação:
# Filtrando somente resultados após maio de 2020 e das unidades da federação
covid_uf = covid.query('(data>"2020-05-31") & (state!="TOTAL") ')
covid_uf
E, por fim, vamos utilizar o método scatter da biblioteca plotly express para construir o motion chart:
# Importando as bibliotecas necessarias
import plotly.express as px
# Construindo o diagrama de dispersão customizado
fig = px.scatter(
data_frame = covid_uf,
x = "totalCases_per_100k_inhabitants",
y = "deaths_per_100k_inhabitants",
title = "<b>Prevalência x Mortalidade Acumulada por Covid-19 por UF</b><br>Brasil, jun/20 - mar/22.",
labels = {
'totalCases_per_100k_inhabitants':'Total de Casos de Covid-19 por 100 mil habitantes',
'deaths_per_100k_inhabitants':'Total de Mortes de Covid-19 por 100 mil habitantes'
},
animation_frame = "date",
animation_group = "state",
color = "Nome_Regiao",
color_discrete_sequence = ['deeppink','orange','blue','lime','dimgrey'],
hover_name = "state",
range_x = [0,30000],
range_y = [0,500],
width = 800,
height = 600,
template = 'simple_white'
)
# Customizando fonte, orientação e posição da legenda
fig.update_layout(
font_family = "Rockwell",
legend = dict(
title = None, orientation = "h", y = -0.5, yanchor = "bottom", x = 0.5, xanchor = "center"
)
)
# Custommizando os marcadores
fig.update_traces(
marker = dict(size = 14 , line = dict(width = 1, color = 'black')),
selector = dict(mode = 'markers')
)
# Controlando a velocidade da animação (Time is in milliseconds)
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 30
fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 5
# Visualizando o gráfico
fig.show()
Pronto! Espere uns segundos para renderizar, e o seu gráfico animado estará pronto! Confira o resultado no vídeo abaixo.
Para mais detalhes, recomendo que consulte a documentação do plotly:
- https://plotly.com/python/bubble-charts/
- https://plotly.com/python/styling-plotly-express/
- https://plotly.com/python/marker-style/
Por fim, você pode baixar o notebook com todas essas informações diretamente do meu GitHub.
Grande Abraço!
Jonatas Silva do Espirito Santo – https://www.linkedin.com/in/jonatasses/
0 Comentários