O objetivo desta análise é conhecer o perfil epidemiológico dos beneficiários de planos de saúde atendidos em hospitais do Estado da Bahia. Para realização deste trabalho utilizarei dados públicos disponibilizados pela ANS e DATASUS, ao final responderei as seguintes perguntas:
O D-TISS é um painel disponibilizado pela Agência Nacional de Saúde Suplementar (ANS) para consultar dados recebidos através do TISS - Troca de Informação em Saúde Suplementar. Com e esta base é possível visualizar a quantidade e o valor médio praticado em procedimentos ambulatoriais (médicos, laboratórios, clínicas) e a quantidade dos procedimentos realizados em ambiente hospitalar dos estabelecimentos que prestam serviço às operadoras de planos de saúde. Atualmente, quase 3.000 procedimentos realizados na saúde suplementar estão disponíveis para consulta no D‐TISS. O período inicial dos dados compreende os meses de julho de 2015 a dezembro de 2016. Os dados disponibilizados correspondem a 901 operadoras, cujas informações de valores de eventos de atenção à saúde informados no TISS correspondem a 64,5% das despesas assistenciais do setor informadas no DIOPS no período.
A base de dados D-TISS utilizada está disponível em:
São 18 arquivos, cada um correspondendo a um mês.
A CID-10 foi conceituada para padronizar e catalogar as doenças e problemas relacionados à saúde, tendo como referência a Nomenclatura Internacional de Doenças, estabelecida pela Organização Mundial de Saúde, que tem por objetivo criar uma codificação padrão para as doenças.
A CID 10 é formada por uma letra, seguida por três números.
O código formado permite a identificação de todas as doenças conhecidas, bem como de sintomas, queixas de pacientes, aspectos fisiológicos anormais, dentre outros.
A base de dados CID-10 utilizada está disponível em: http://www.datasus.gov.br/cid10/V2008/cid10.htm
São 4 arquivos, CID-10-CAPITULOS, CID-10-GRUPOS, CID-10-CATEGORIAS e CID-10-SUBCATEGORIAS.
In [1]:
import pandas as pd
from pandas import DataFrame
import numpy as np
import random
from datetime import datetime, timedelta
import time
import matplotlib.pyplot as plt
import matplotlib as mpl
from IPython.display import Image
from sklearn.metrics import mean_squared_error
import seaborn as sns
from scipy.stats import boxcox
import warnings
# Import statsmodel
import statsmodels.api as sm
import statsmodels.formula.api as smf
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.tsa.arima_model import ARIMAResults
from math import sqrt
%matplotlib inline
In [53]:
# Carregando a base de dados D-TISS
data1 = pd.read_csv('tb_TISS_BA_1507_H.csv', decimal=b',')
data2 = pd.read_csv('tb_TISS_BA_1508_H.csv', decimal=b',')
data3 = pd.read_csv('tb_TISS_BA_1509_H.csv', decimal=b',')
data4 = pd.read_csv('tb_TISS_BA_1510_H.csv', decimal=b',')
data5 = pd.read_csv('tb_TISS_BA_1511_H.csv', decimal=b',')
data6 = pd.read_csv('tb_TISS_BA_1512_H.csv', decimal=b',')
data7 = pd.read_csv('tb_TISS_BA_1601_H.csv', decimal=b',')
data8 = pd.read_csv('tb_TISS_BA_1602_H.csv', decimal=b',')
data9 = pd.read_csv('tb_TISS_BA_1603_H.csv', decimal=b',')
data10 = pd.read_csv('tb_TISS_BA_1604_H.csv', decimal=b',')
data11 = pd.read_csv('tb_TISS_BA_1605_H.csv', decimal=b',')
data12 = pd.read_csv('tb_TISS_BA_1606_H.csv', decimal=b',')
data13 = pd.read_csv('tb_TISS_BA_1607_H.csv', decimal=b',')
data14 = pd.read_csv('tb_TISS_BA_1608_H.csv', decimal=b',')
data15 = pd.read_csv('tb_TISS_BA_1609_H.csv', decimal=b',')
data16 = pd.read_csv('tb_TISS_BA_1610_H.csv', decimal=b',')
data17 = pd.read_csv('tb_TISS_BA_1611_H.csv', decimal=b',')
data18 = pd.read_csv('tb_TISS_BA_1612_H.csv', decimal=b',')
# Unindo os 18 arquivos da base D-TISS en um único Dataframe
d_tiss = pd.concat([data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15, data16, data17, data18], ignore_index=True)
#Carregando a base de dados CID-10
cid_capitulo = pd.read_csv('CID-10-CAPITULOS.csv', sep=';', encoding='latin-1')
cid_grupo = pd.read_csv('CID-10-GRUPOS.csv', sep=';', encoding='latin-1')
cid_categoria = pd.read_csv('CID-10-CATEGORIAS.csv', sep=';', encoding='latin-1')
cid_subcategorias = pd.read_csv('CID-10-SUBCATEGORIAS.csv', sep=';', encoding='latin-1')
In [3]:
print('O Dataframe d_tiss possui ' + str(d_tiss.shape[0]) + ' linhas e ' + str(d_tiss.shape[1]) + ' colunas')
In [4]:
print('O Dataframe cid_capitulo possui ' + str(cid_capitulo.shape[0]) + ' linhas e ' + str(cid_capitulo.shape[1]) + ' colunas')
In [5]:
print('O Dataframe cid_grupo possui ' + str(cid_grupo.shape[0]) + ' linhas e ' + str(cid_grupo.shape[1]) + ' colunas')
In [6]:
print('O Dataframe cid_categoria possui ' + str(cid_categoria.shape[0]) + ' linhas e ' + str(cid_categoria.shape[1]) + ' colunas')
In [7]:
print('O Dataframe cid_subcategorias possui ' + str(cid_subcategorias.shape[0]) + ' linhas e ' + str(cid_subcategorias.shape[1]) + ' colunas')
In [8]:
Image(url = 'Dicionario_de_variaveis_dtiss.png')
Out[8]:
In [9]:
Image(url = 'Dicionario-de-variaveis-cid-10.png')
Out[9]:
In [10]:
##### Visualizando as primeiras 10 linhas do dataframe d_tiss
d_tiss.head(10)
Out[10]:
In [11]:
# Sumário dos dados
d_tiss.describe()
Out[11]:
In [12]:
d_tiss.dtypes
Out[12]:
In [13]:
# Visualizando as primeiras 10 linhas do dataframe cid_capitulo
cid_capitulo.head(10)
Out[13]:
In [14]:
cid_capitulo.dtypes
Out[14]:
In [15]:
# Visualizando as primeiras 10 linhas do dataframe cid_categorias
cid_categoria.head(10)
Out[15]:
In [16]:
cid_categoria.dtypes
Out[16]:
In [17]:
# Visualizando as primeiras 10 linhas do dataframe cid_subcategorias
cid_subcategorias.head(10)
Out[17]:
In [18]:
cid_subcategorias.dtypes
Out[18]:
Primeiramente eliminarei algumas colunas da base de dados D-TISS que não interessam para análise proposta. Começarei pelas colunas CID_2, CID_3, CID_4, pois trabalharei apenas com o CID primeiro diagnóstico ou diagnóstico principal. Eliminarei também as colunas IDENTIFICACAO_OPERADORA e IDENTIFICACAO_PRESTADOR, pois de acordo com o dicionário de variáveis D-TISS são informações criptografadas, depois as colunas PORTE_OPERADORA e UF_PRESTADOR.
In [54]:
# Criando um novo dataframe a partir do d_tiss
d_tiss_tratado = d_tiss.copy()
# Eliminando colunas que não serão utilizadas
d_tiss_tratado.drop(['CID_2', 'CID_3', 'CID_4', 'IDENTIFICACAO_OPERADORA', 'IDENTIFICACAO_PRESTADOR',
'PORTE_OPERADORA', 'UF_PRESTADOR'], axis = 1, inplace = True)
# Transformando a coluna CID_1 para o tipo str
d_tiss_tratado['CID_1'] = d_tiss_tratado['CID_1'].astype('str')
Como o objetivo principal da análise é conhecer o perfil epidemiológico dos beneficiários de planos de saúde do Estado da Bahia atendidos em hospitais, faz-se necessário eliminar os registros que não possui o CID diagnóstico principal.
In [71]:
# Eliminando os registros que não possui o CID Diagnostico principal
d_tiss_tratado = d_tiss_tratado[(d_tiss_tratado.CID_1 != '-1') & (d_tiss_tratado.CID_1 != '-2')]
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado.shape[0]) + ' linhas e ' + str(d_tiss_tratado.shape[1]) + ' colunas')
Após excluir os registros que não possui o CID de diagnóstico principal, restaram 162131 linhas e 10 colunas. Agora será necessário acrescentar outras colunas para ajudar no processo de análise e responder as perguntas. Começarei realizando uma série de operações cujo objetivo é unir informações para que seja possível identtificar a Classificação Estatística Internacional de Doenças e Problemas Relacionados com a Saúde de acordo com o Capítulo, Categoria e Subcategoria do CID primeiro diagnóstico ou diagnóstico principal.
In [56]:
# Função para localizar um caracter detro de uma string
def find(str1, ch):
indice = 0
while indice < len(str1):
if str1[indice] == ch:
return indice
indice = indice + 1
return -1
In [57]:
# Criando os dataframes cid_capit e cid_subcat
cid_capit = cid_capitulo[['NUMCAP','DESCRICAO']].copy()
cid_categ = cid_categoria[['CAT','DESCRICAO']].copy()
cid_subcat = cid_subcategorias[['SUBCAT','RESTRSEXO', 'DESCRICAO']].copy()
# Renomeando as colunas do dataframe cid_categ
cid_categ.columns = ['CID_CAT','CID_CATEGORIA']
# Renomeando as colunas do dataframe cid_capit
cid_capit.columns = ['CID_NUMCAP','CID_CAPITULO']
# Eliminado da descrição do capítulo a parte que faz referencia ao capítulo em si
cid_capit['CID_CAPITULO'] = cid_capit.apply(lambda row: ''.join(row['CID_CAPITULO'])[find(''.join(row['CID_CAPITULO']),'-')+2:len(''.join(row['CID_CAPITULO']))],axis=1)
# Renomeando as colunas do dataframe cid_subcat
cid_subcat.columns = ['CID_SUBCAT','CID_RESTRSEX','CID_SUBCATEGORIA']
In [59]:
# Identificando em qual capítulo do CID o CID do diagnóstico principal pertence
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 1 if (row['CID_1'][0:3].strip() >= 'A00') & (row['CID_1'][0:3].strip() <= 'B99') else '-1', axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 2 if (row['CID_1'][0:3].strip() >= 'C00') & (row['CID_1'][0:3].strip() <= 'D48') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 3 if (row['CID_1'][0:3].strip() >= 'D50') & (row['CID_1'][0:3].strip() <= 'D89') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 4 if (row['CID_1'][0:3].strip() >= 'E00') & (row['CID_1'][0:3].strip() <= 'E90') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 5 if (row['CID_1'][0:3].strip() >= 'F00') & (row['CID_1'][0:3].strip() <= 'F99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 6 if (row['CID_1'][0:3].strip() >= 'G00') & (row['CID_1'][0:3].strip() <= 'G99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 7 if (row['CID_1'][0:3].strip() >= 'H00') & (row['CID_1'][0:3].strip() <= 'H59') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 8 if (row['CID_1'][0:3].strip() >= 'H60') & (row['CID_1'][0:3].strip() <= 'H95') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 9 if (row['CID_1'][0:3].strip() >= 'I00') & (row['CID_1'][0:3].strip() <= 'I99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 10 if (row['CID_1'][0:3].strip() >= 'J00') & (row['CID_1'][0:3].strip() <= 'J99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 11 if (row['CID_1'][0:3].strip() >= 'K00') & (row['CID_1'][0:3].strip() <= 'K93') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 12 if (row['CID_1'][0:3].strip() >= 'L00') & (row['CID_1'][0:3].strip() <= 'L99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 13 if (row['CID_1'][0:3].strip() >= 'M00') & (row['CID_1'][0:3].strip() <= 'M99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 14 if (row['CID_1'][0:3].strip() >= 'N00') & (row['CID_1'][0:3].strip() <= 'N99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 15 if (row['CID_1'][0:3].strip() >= 'O00') & (row['CID_1'][0:3].strip() <= 'O99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 16 if (row['CID_1'][0:3].strip() >= 'P00') & (row['CID_1'][0:3].strip() <= 'P96') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 17 if (row['CID_1'][0:3].strip() >= 'Q00') & (row['CID_1'][0:3].strip() <= 'Q99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 18 if (row['CID_1'][0:3].strip() >= 'R00') & (row['CID_1'][0:3].strip() <= 'R99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 19 if (row['CID_1'][0:3].strip() >= 'S00') & (row['CID_1'][0:3].strip() <= 'T98') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 20 if (row['CID_1'][0:3].strip() >= 'V01') & (row['CID_1'][0:3].strip() <= 'Y98') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 21 if (row['CID_1'][0:3].strip() >= 'Z00') & (row['CID_1'][0:3].strip() <= 'Z99') else row['CID_NUMCAP'], axis=1)
d_tiss_tratado['CID_NUMCAP'] = d_tiss_tratado.apply(lambda row: 22 if (row['CID_1'][0:3].strip() >= 'U04') & (row['CID_1'][0:3].strip() <= 'U99') else row['CID_NUMCAP'], axis=1)
In [24]:
d_tiss_tratado2 = d_tiss_tratado.copy()
In [ ]:
d_tiss_tratado = d_tiss_tratado2.copy()
In [ ]:
d_tiss_tratado.dtypes
In [61]:
# Identificando em qual categoria do CID o CID subcategoria pertence
d_tiss_tratado['CID_CAT'] = d_tiss_tratado.apply(lambda row: row['CID_1'][0:3], axis=1)
# Fazendo merge com os dataframes cid_capit, cid_categ, sid_subcateg
d_tiss_tratado = d_tiss_tratado.merge(cid_capit, left_on='CID_NUMCAP', right_on='CID_NUMCAP', how='left')
d_tiss_tratado = d_tiss_tratado.merge(cid_categ, left_on='CID_CAT', right_on='CID_CAT', how='left')
d_tiss_tratado = d_tiss_tratado.merge(cid_subcat, left_on='CID_1', right_on='CID_SUBCAT', how='left')
In [26]:
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado[(d_tiss_tratado.CD_SEXO == -1)].shape[0]) +
' linhas que não possuem a informação de sexo do beneficiário informado')
Após eliminar os registros que não possuíam o CID diagnostico principal restaram 162131 linhas, sendo que destas 11162 não possuem a informação do sexo do beneficiário. Alguns CIDs são restritos ao sexo do paciente, através desta informação é possível identificar o sexo de alguns beneficiários que não possui o registro desta informação. Usarei este recurso para preencher sexo de alguns pacientes que falta esta informação.
In [63]:
# Atualizando a coluna CD_SEXO dos registros faltantes de acordo com o campo RESTRSEXO correspondente ao CID diagnóstico principal
d_tiss_tratado['CD_SEXO'] = d_tiss_tratado.apply(lambda row: 1 if (row['CID_RESTRSEX'] == 'M') else row['CD_SEXO'], axis=1)
d_tiss_tratado['CD_SEXO'] = d_tiss_tratado.apply(lambda row: 3 if (row['CID_RESTRSEX'] == 'F') else row['CD_SEXO'], axis=1)
In [28]:
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado[(d_tiss_tratado.CD_SEXO == -1)].shape[0]) + ' linhas sem o sexo do beneficiário informado')
Após preencher a coluna CD_SEXO de acordo com a coluna RESTRSEXO correspondente ao CID diagnóstico principal restaram 9517 sem a informação do sexo do beneficiário. Agora utilizarei uma outra abordagem para preencher o sexo do beneficiário dos 9517 registros que restaram através da maior frequência por CID diagnóstico principal.
In [29]:
# Alterando o valores faltantes da coluna CD_SEXO de -1 para NaN
d_tiss_tratado['CD_SEXO'] = d_tiss_tratado.apply(lambda row: np.nan if (row['CD_SEXO'] == -1) else row['CD_SEXO'], axis=1)
# Criando um novo dataframe com a frequencia de sexo por CID
frequencia_sexo = d_tiss_tratado.groupby(["CID_1","CD_SEXO"]).CD_SEXO.count().astype('int64').reset_index(name='FREQUENCIA_SEXO')
# Agrupando o sexo mais frequente por CID
frequencia_sexo = frequencia_sexo.groupby(["CD_SEXO","CID_1"]).FREQUENCIA_SEXO.max().astype('int64').reset_index(name='FREQUENCIA_SEXO')
# Eliminando a coluna FREQUENCIA_SEXO
frequencia_sexo.drop('FREQUENCIA_SEXO', axis = 1, inplace = True)
# Renomeando as coluna
frequencia_sexo.columns = ['CD_SEXO_MAIS_FREQUENTE','CID_1']
# Fazendo merge com os dataframes frequencia_sexo e d_tiss_tratado
d_tiss_tratado = d_tiss_tratado.merge(frequencia_sexo, left_on='CID_1', right_on='CID_1', how='left')
d_tiss_tratado['CD_SEXO'].fillna(d_tiss_tratado['CD_SEXO_MAIS_FREQUENTE'], inplace=True)
d_tiss_tratado['CD_SEXO'].fillna(-1, inplace=True)
d_tiss_tratado['CD_SEXO'] = d_tiss_tratado['CD_SEXO'].astype('int64')
d_tiss_tratado.drop('CD_SEXO_MAIS_FREQUENTE', axis = 1, inplace = True)
In [30]:
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado[(d_tiss_tratado.CD_SEXO == -1)].shape[0]) + ' linhas sem o sexo do beneficiário informado')
In [31]:
d_tiss_tratado.head()
Out[31]:
In [66]:
# Separando em colunas sexo masculino e sexo feminino a partir da coluna CD_SEXO
d_tiss_tratado['FEMININO'] = d_tiss_tratado.apply(lambda row: 1 if (row['CD_SEXO'] == 3) else 0, axis=1)
d_tiss_tratado['MASCULINO'] = d_tiss_tratado.apply(lambda row: 1 if (row['CD_SEXO'] == 1) else 0, axis=1)
In [33]:
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado[(d_tiss_tratado.IDADE_BENEFICIARIO == -1)].shape[0]) +
' linhas que não possuem a informação de idade do beneficiário informado')
Utilizarei como estratégia para preenchimento da idade dos beneficiários que não possuem esta informação a média das idades agrupadas por CID. Primeiramente irei criar um novo dataframe contendo o CID e a média de idade com base no dataframe d_tiss_tratado, depois farei um merge e por último farei um apply na idade dos beneficiários que estão sem essa informação.
In [68]:
# Criando um novo dataframe com a media de idade por CID
media_idade = d_tiss_tratado.groupby(["CID_1"]).IDADE_BENEFICIARIO.mean().astype('int64').reset_index(name='MEDIA_IDADE')
# Fazendo um merge do dataframe media_idade com o dataframe d_tiss_tratado para acrescentar a coluna MEDIA_IDADE
d_tiss_tratado = d_tiss_tratado.merge(media_idade, left_on='CID_1', right_on='CID_1', how='left')
# Atualizando a coluna IDADE_BENEFICIARIO de acordo com o campo MEDIA_IDADE por CID diagnóstico principal, apenas para os registros faltantes
d_tiss_tratado['IDADE_BENEFICIARIO'] = d_tiss_tratado.apply(lambda row: row['MEDIA_IDADE'] if (row['IDADE_BENEFICIARIO'] == -1) else row['IDADE_BENEFICIARIO'], axis=1)
In [35]:
print('O Dataframe d_tiss_tratado possui ' + str(d_tiss_tratado[(d_tiss_tratado.IDADE_BENEFICIARIO == -1)].shape[0]) +
' linhas que não possuem a informação de idade do beneficiário informado')
In [36]:
d_tiss_tratado.dtypes
Out[36]:
In [70]:
# Criando a faixa etária de acordo com a classificação do IBGE
bins = [0,4,9,14,19,24,29,34,39,44,49,54,59,64,69,74,79,84,89,94,99,200]
labels=['0 a 4 anos','5 a 9 anos','10 a 14 anos','15 a 19 anos','20 a 24 anos','25 a 29 anos','30 a 34 anos','35 a 39 anos','40 a 44 anos','45 a 49 anos','50 a 54 anos','55 a 59 anos','60 a 64 anos','65 a 69 anos','70 a 74 anos','75 a 79 anos','80 a 84 anos','85 a 89 anos','90 a 94 anos','95 a 99 anos','Mais de 100 anos']
#labels=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]
d_tiss_tratado['FAIXA_ETARIA'] = pd.cut(d_tiss_tratado['IDADE_BENEFICIARIO'], bins=bins, labels=labels, include_lowest=True)
In [38]:
d_tiss_tratado.dtypes
Out[38]:
In [50]:
d_tiss_tratado.describe()
Out[50]:
In [ ]:
# Salvando dataset tratado
d_tiss_tratado.to_csv('d_tiss_tratado.csv')
In [73]:
# Criando um dataframe para construir uma piramide etária
piramide_etaria = d_tiss_tratado.groupby("FAIXA_ETARIA")["FEMININO","MASCULINO","VALOR_PROCEDIMENTO"].sum().reset_index()
piramide_etaria["PERC_FEMININO"] = (piramide_etaria["FEMININO"] / (piramide_etaria["FEMININO"]+piramide_etaria["MASCULINO"])).astype('float64')
piramide_etaria["PERC_MASCULINO"] = (piramide_etaria["MASCULINO"] / (piramide_etaria["FEMININO"]+piramide_etaria["MASCULINO"])).astype('float64')
piramide_etaria["VALOR_FEMININO"] = round(piramide_etaria["VALOR_PROCEDIMENTO"] * piramide_etaria["PERC_FEMININO"],2)
piramide_etaria["VALOR_MASCULINO"] = round(piramide_etaria["VALOR_PROCEDIMENTO"] * piramide_etaria["PERC_MASCULINO"],2)
piramide_etaria["MASCULINO"] = piramide_etaria["MASCULINO"] * -1
In [42]:
piramide_etaria
Out[42]:
In [192]:
piramide_etaria.dtypes
Out[192]:
Primeiramente irei construir uma Pirâmide Etária para conhecermos em quais faixa etária concentram-se os atendimentos. A Pirâmide Etária é um gráfico que permite analisar a distribuição da população por idade e sexo.
In [40]:
#Cores para serem usadas nos gráficos
colors = [['#0D47A1','#1565C0','#1976D2','#1E88E5','#2196F3'],
['#311B92','#512DA8','#673AB7','#9575CD','#B39DDB'],
['#1B5E20','#388E3C','#4CAF50','#81C784','#66BB6A'],
['#E65100','#EF6C00','#F57C00','#FB8C00','#FF9800'],
['#3E2723','#4E342E','#5D4037','#6D4C41','#795548'],
['#BF360C','#D84315','#E64A19','#F4511E','#FF5722'],
['#880E4F','#AD1457','#C2185B','#D81B60','#E91E63']
]
In [184]:
sns.set_style("white")
fig = plt.figure(figsize=(12,8))
plt.xlim(-16000, 16000)
bar_plot1 = sns.barplot(x="MASCULINO",y="FAIXA_ETARIA",
order=['Mais de 100 anos','95 a 99 anos','90 a 94 anos','85 a 89 anos','80 a 84 anos','75 a 79 anos','70 a 74 anos','65 a 69 anos','60 a 64 anos','55 a 59 anos','50 a 54 anos','45 a 49 anos','40 a 44 anos','35 a 39 anos','30 a 34 anos','25 a 29 anos','20 a 24 anos','15 a 19 anos','10 a 14 anos','5 a 9 anos','0 a 4 anos'],
orient = 'h',color="blue", label="Homens",data = piramide_etaria)
for p in bar_plot1.axes.patches:
b=p.get_bbox()
bar_plot1.axes.annotate("{:.0f}".format(-b.x0), (-p.get_width() - 500, p.get_y() + 0.4), size=8,
va='center', ha='right', bbox=dict(boxstyle='square', fc = 'w'))
plt.legend(loc='upper left')
bar_plot2 = sns.barplot(x="FEMININO",y="FAIXA_ETARIA",
order=['Mais de 100 anos','95 a 99 anos','90 a 94 anos','85 a 89 anos','80 a 84 anos','75 a 79 anos','70 a 74 anos','65 a 69 anos','60 a 64 anos','55 a 59 anos','50 a 54 anos','45 a 49 anos','40 a 44 anos','35 a 39 anos','30 a 34 anos','25 a 29 anos','20 a 24 anos','15 a 19 anos','10 a 14 anos','5 a 9 anos','0 a 4 anos'],
orient = 'h', color="red", label="Mulheres",data = piramide_etaria)
for p in bar_plot2.axes.patches:
b=p.get_bbox()
if b.x1 > 0:
bar_plot2.axes.annotate("{:.0f}".format(b.x1), (p.get_x() + p.get_width() + 500, p.get_y() + 0.4), size=8,
va='center', ha='left', bbox=dict(boxstyle='square', fc = 'w'))
plt.legend(loc='best')
# Ocultar eixo x
#bar_plot1.axes.get_xaxis().set_visible(False)
#bar_plot2.axes.get_xaxis().set_visible(False)
#bar_plot2.set(xlabel="Atendimentos", ylabel="Faixa Etária", title = "Piramide Etária")
bar_plot1.set(xlabel="Atendimentos", ylabel="Faixa Etária", title = "Piramide Etária")
sns.despine(left=True)
plt.show()
Através do gráfico acima podemos observar que é na população feminina entre 30 e 39 anos que registra-se o maior volume de atendimentos. Considerando toda população em estudo podemos concluir que as mulheres são as que mais utilizam plano o de saúde.
In [ ]:
Com base na Classificação Internacional de Doenças vamos avaliar a distribuição de atendimentos por classificação de doenças para identificar-mos quais as principais doenças dos beneficiários de plano de saude da Bahia.
In [79]:
# Grafico - Volume de atendimentos por capitulo
ax = d_tiss_tratado.groupby('CID_CAPITULO')['ID_EVENTO'].count().sort_values().plot(kind='barh', color=random.choice(colors), figsize=(10,10))
sns.despine(left=True)
for p in ax.patches:
b=p.get_bbox()
ax.annotate("{:.0f}".format(b.x1 + b.x0), (p.get_x() + p.get_width() + 1, p.get_y() - 0.05))
plt.title('ATENDIMENTOS REALIZADOS POR CAPÍTULO \n Total: ' + str(d_tiss_tratado['ID_EVENTO'].count()) + ' Atendimentos')
plt.ylabel('CAPITULOS')
plt.xlabel('QUANTIDADE DE ATENDIMENTOS', )
plt.show()
Através do gráfico acima podemos perceber que os três principais Capítulos são: Doenças do aparelho geniturinário é o Capítulo que possui maior incidência diagnóstica na população, em seguida vem Sintomas, sinais e achados anormais de exames clínicos e de laboratório, não classificados em outra parte e depois doenças do aparelho circulatório.
Sinais e sintomas que conduzam de forma razoavelmente precisa a um dado diagnóstico estão classificados em categorias de outros capítulos desta classificação. De modo geral, as categorias deste capítulo incluem aqueles sintomas e afecções menos bem definidas que, sem que tenha havido o necessário estudo do caso para se estabelecer um diagnóstico final, podem conduzir com igual possibilidade a duas ou mais doenças diferentes ou a dois ou mais aparelhos do corpo. Praticamente todas as categorias deste capítulo se poderiam designar como “não especificado de outra forma”, “etiologia desconhecida” ou “transitório”. O Índice Alfabético deve ser consultado para se determinar quais sintomas e sinais devem ser alocados aqui e quais a outros capítulos. As subcategorias residuais .8 são fornecidas para outros sintomas relevantes que não possam ser classificados em outras partes da classificação. As afecções e sinais ou sintomas incluídos nas categorias R00-R99 consistem de: a) casos para os quais não se possa chegar a um diagnóstico mais preciso, mesmo depois que todos os fatos que digam respeito ao caso tenham sido investigados; b) sinais ou sintomas existentes no momento da primeira consulta que se mostrem de caráter transitório e cujas causas não possam ser determinadas; c) diagnósticos provisórios atribuídos a um paciente que não retorne a consulta para aprofundamento da investigação do diagnóstico ou para assistência; d) casos encaminhados a outros locais para investigação ou tratamento antes que o diagnóstico fosse feito; e) casos para os quais não foi possível estabelecer um diagnóstico mais preciso por qualquer outra razão; f) alguns sintomas para os quais se fornece informação complementar e que representam por si só importantes problemas na assistência médica.
Fonte: http://www.datasus.gov.br/cid10/V2008/WebHelp/r00_r99.htm
In [80]:
# Grafico - Volume de atendimentos por capitulo - Sexo masculino, excuindo-se o capítulo XVIII
ax = d_tiss_tratado[(d_tiss_tratado.CD_SEXO == 1) & (d_tiss_tratado.CID_NUMCAP != 18)].groupby('CID_CAPITULO')['ID_EVENTO'].count().sort_values().plot(kind='barh', color=random.choice(colors), figsize=(10,10))
sns.despine(left=True)
for p in ax.patches:
b=p.get_bbox()
ax.annotate("{:.0f}".format(b.x1 + b.x0), (p.get_x() + p.get_width() + 1, p.get_y() - 0.05))
plt.title('ATENDIMENTOS REALIZATDOS POR CAPÍTULO \n Total: ' + str(d_tiss_tratado[(d_tiss_tratado.CD_SEXO == 1)]['ID_EVENTO'].count()) + ' Atendimentos')
plt.ylabel('CAPÍTULOS')
plt.xlabel('QUANTIDADE DE ATENDIMENTOS - SEXO MASCULINO', )
plt.show()
Quando olhamos separadamente por sexo, as três principais classificações de doenças que mais ocorrem para os homens são: Doenças do aparelho circulatório, Doenças do aparelho geniturinário e Doenças do aparelho respiratório.
In [129]:
# Grafico - Volume de atendimentos por capitulo - Sexo feminino, excuindo-se o capítulo XVIII
ax = d_tiss_tratado[(d_tiss_tratado.CD_SEXO == 3) & (d_tiss_tratado.CID_NUMCAP != 18)].groupby('CID_CAPITULO')['ID_EVENTO'].count().sort_values().plot(kind='barh', color=random.choice(colors), figsize=(10,10))
sns.despine(left=True)
for p in ax.patches:
b=p.get_bbox()
ax.annotate("{:.0f}".format(b.x1 + b.x0), (p.get_x() + p.get_width() + 1, p.get_y() - 0.05))
plt.title('ATENDIMENTOS REALIZADOS POR CAPÍTULO \n Total: ' + str(d_tiss_tratado[(d_tiss_tratado.CD_SEXO == 3)]['ID_EVENTO'].count()) + ' Atendimentos')
plt.ylabel('CAPÍTULOS')
plt.xlabel('QUANTIDADE DE ATENDIMENTOS - SEXO FEMININO', )
plt.show()
Já para as mulheres temos Gravidez, parto e puerpério, em seguida vem as Doenças do aparelho geniturinário e depois Doenças do aparelho circulatório.
In [130]:
# As 10 principais Categorias de Doenças do aparelho geniturinário
ax = d_tiss_tratado[(d_tiss_tratado.CID_NUMCAP == 14)].groupby('CID_CATEGORIA')['MASCULINO','FEMININO'].sum().sort_values(by=['MASCULINO','FEMININO'], ascending=False).iloc[:10].plot(kind='barh', color=random.choice(colors), figsize=(10,10))
sns.despine(left=True)
ax.invert_yaxis()
for p in ax.patches:
b=p.get_bbox()
ax.annotate("{:.0f}".format(b.x1 + b.x0), (p.get_x() + p.get_width() + 1, p.get_y() + 0.2))
plt.title('DOENÇAS DO APARELHO GENITURINÁRIO \n 10 Principais Categorias')
plt.ylabel('CATEGORIA')
plt.xlabel('QUANTIDADE DE ATENDIMENTOS', )
plt.show()
Já na classificação Doenças do aparelho genituário a Calculose do rim e do ureter se destaca como a categoria de doença mais frequente, sendo que dentre os casos diagnosticados, 59% ocorreram em Homens e 41% em Mulheres.
In [82]:
# As 10 principais Cateorias de Doenças do aparelho circulatório
ax = d_tiss_tratado[(d_tiss_tratado.CID_NUMCAP == 9)].groupby('CID_CATEGORIA')['FEMININO','MASCULINO'].sum().sort_values(by=['FEMININO','MASCULINO'], ascending=False).iloc[:10].plot(kind='barh', color=random.choice(colors), figsize=(10,10))
sns.despine(left=True)
ax.invert_yaxis()
for p in ax.patches:
b=p.get_bbox()
ax.annotate("{:.0f}".format(b.x1 + b.x0), (p.get_x() + p.get_width() + 1, p.get_y() + 0.2))
plt.title('DOENÇAS DO APARELHO CIRCULATÓRIO \n 10 Principais Categorias')
plt.ylabel('CATEGORIA')
plt.xlabel('QUANTIDADE DE ATENDIMENTOS', )
plt.show()