Análise exploratória de casos de Zika notificado pelo SUS

Neste tutorial vamos explorar como começar a entender a descrição de casos do sistema de notificação de agravos do SUS, o SINAN. Estes dados são bastante ricos e a documentação sobre o significado de cada uma das variáveis pode ser encontrada aqui.

[1]:
from pysus.online_data import SINAN, parquets_to_dataframe
%pylab inline
%pylab is deprecated, use %matplotlib inline and import the required libraries.
Populating the interactive namespace from numpy and matplotlib

Primeiro vamos começar pelo carregamento dos dados a partir do site do InfoDengue. Como o dado está no formato parquet, nós vamos utilizar a biblioteca pandas para carregar os dados em um Dataframe.

[2]:
cols = [
    'ID_AGRAVO', 'DT_NOTIFIC', 'SEM_NOT', 'NU_ANO', 'ID_MUNICIP',
    'DT_SIN_PRI', 'SEM_PRI', 'NU_IDADE_N', 'CS_SEXO', 'CS_GESTANT',
    'latitude', 'longitude',
    'NM_DISEASE'
]
casos = parquets_to_dataframe(SINAN.download('Zika', 2016))

Vejamos os nomes da variáveis

[3]:
casos.columns
[3]:
Index(['TP_NOT', 'ID_AGRAVO', 'CS_SUSPEIT', 'DT_NOTIFIC', 'SEM_NOT', 'NU_ANO',
       'SG_UF_NOT', 'ID_MUNICIP', 'ID_REGIONA', 'DT_SIN_PRI', 'SEM_PRI',
       'NU_IDADE_N', 'CS_SEXO', 'CS_GESTANT', 'CS_RACA', 'CS_ESCOL_N', 'SG_UF',
       'ID_MN_RESI', 'ID_RG_RESI', 'ID_PAIS', 'NDUPLIC_N', 'IN_VINCULA',
       'DT_INVEST', 'ID_OCUPA_N', 'CLASSI_FIN', 'CRITERIO', 'TPAUTOCTO',
       'COUFINF', 'COPAISINF', 'COMUNINF', 'DOENCA_TRA', 'EVOLUCAO',
       'DT_OBITO', 'DT_ENCERRA', 'CS_FLXRET', 'FLXRECEBI', 'TP_SISTEMA',
       'TPUNINOT'],
      dtype='object')
[4]:
# casos = casos[casos.ID_AGRAVO=='A928']
casos.head()
[4]:
TP_NOT ID_AGRAVO CS_SUSPEIT DT_NOTIFIC SEM_NOT NU_ANO SG_UF_NOT ID_MUNICIP ID_REGIONA DT_SIN_PRI ... COPAISINF COMUNINF DOENCA_TRA EVOLUCAO DT_OBITO DT_ENCERRA CS_FLXRET FLXRECEBI TP_SISTEMA TPUNINOT
0 2 A928 2016-01-01 201552 2016 17 170230 2016-01-01 ... 0 20160307 0 2 1
1 2 A928 2016-01-01 201552 2016 29 292040 1385 2015-12-29 ... 1 292040 2 1 20160602 0 2 1
2 2 A928 2016-01-01 201552 2016 29 292040 1385 2016-01-01 ... 1 292040 2 1 20160602 0 2 1
3 2 A928 2016-01-01 201552 2016 29 293240 1394 2015-12-28 ... 1 293240 2 1 20160102 0 2 1
4 2 A928 2016-01-01 201552 2016 32 320530 1510 2015-12-31 ... 1 320530 2 1 20160125 0 2 1

5 rows × 38 columns

Estes dados correspondem a todos os casos de Zika notificados ao SUS durante um período. Neste caso de 2015 a 2016. Para podermos tratar adequadamente estes dados para fins de visualização ou análise precisamos corrigir os tipos das colunas. Por exemplo vamos converter as datas.

[5]:
import pandas as pd
casos['DT_INDEX'] = pd.to_datetime(casos.DT_NOTIFIC)

Para poder organizar os dados temporalmente, é útil indexar a tabela por alguma variável temporal. Vamos usar a data de notifiacão de cada caso como índice

[6]:
casos = casos.set_index('DT_INDEX')

Agora podemos plotar o número de casos por semana de dengue na cidade do Rio de Janeiro.

[7]:
casos.ID_AGRAVO.resample('1W').count().plot()
[7]:
<Axes: xlabel='DT_INDEX'>
_images/Zika_12_1.png

Suponhamos agora que desejamos visualizar em um mapa os casos que ocorreram, por exemplo entre janeiro e agosto de 2016.

Usando Kepler.gl para visualização

[8]:
import keplergl
import os
import json
if os.path.exists('kepler_config.json'):
    config = json.load(open('kepler_config.json','r'))
w1 = keplergl.KeplerGl(height=600, config=config)
User Guide: https://docs.kepler.gl/docs/keplergl-jupyter
[14]:
df = casos.dropna()
df['DT_NOTIFIC'] = df['DT_NOTIFIC'].astype('string')
df['DT_SIN_PRI'] = df['DT_SIN_PRI'].astype('string')
df.index = df.index.astype('string')
w1.add_data(df, name='Casos de Zika em 2016')
[15]:
w1.show()
[10]:
#Salvando a configuração.
# execute apenas se desejar preservar a configuração atual para sessões futuras.
json.dump(w1.config, open('kepler_config.json','w'))