Este documento é um projeto de obtenção, limpeza, armazenamento e análise de dados da área da saúde. Foi criado para compor meu portfólio pessoal. O documento está dividido em etapas que estão separadas em abas de navegação na página.
Etapas:
Os dados utilizados foram obtidos do Portal Brasileiro de Dados Abertos na página do Sistema de Informaçãoo sobre Mortalidade - SIM que contém dados de 1979 a 2018. Os dados disponibilizados contém 87 ariáveis que estão descritas em um documento.
Para as análises deste relatório foram utilizados os dados entre os anos de 2015 a 2018. e foram utilizadas as seguintes variáveis:
DTOBITO = Data em que occoreu o Óbito (Data no padrão ddmmaaaa)
DTNASC = Data do nascimento do falecido. Em caso de Óbito fetal as datas de Óbitoe nascimento deverão ser iguais.(Data no padrão ddmmaaaa)
ESC = Escolaridade em anos. (1 - Nenhuma; 2 - de 1 a 3 anos; 3 - de 4 a 7 anos; 4- de 8 a 11 anos; 5 - 12 anos e mais; 9 - Ignorado)
ESTCIV = Estado civil. (1: Solteiro; 2: Casado; 3: Viúvo; 4: Separado judicialmente; 5: União consensual; 9: Ignorado)
HORAOBITO = Horário do Óbito. (Números (padrão 24 horas 00:00))
IDADE = Idade do falecido em minutos, horas, dias, meses ou anos. (Idade: composto de dois subcampos. - O primeiro, de 1 dígito, indica a unidade da idade (se 1 = minuto, se 2 = hora, se 3 = mês, se 4 = ano, se = 5 idade maior que 100 anos). - O segundo, de dois dígitos, indica a quantidade de unidades: Idade menor de 1 hora: subcampo varia de 01 e 59 (minutos); De 1 a 23 Horas: subcampo varia de 01 a 23 (horas); De 24 horas e 29 dias: subcampo varia de 01 a 29 (dias); De 1 a menos de 12 meses completos: subcampo varia de 01 a 11 (meses); Anos - subcampo varia de 00 a 99; - 9 - ignorado). Esta coluna será dividida em duas novas colunas antes da insersão no BD (CODIDADE e VALIDADE)
SEXO = Sexo do falecido. - Ignorado em casos especiais como cadáveres mutilados, em estado avançado de decomposição, genitáia indefinida ou hermafroditismo. (M - masculino; F - feminino; I - ignorado)
Pacotes utilizados no projeto
require(ggplot2) # pacote para a criação dos gráficos
require(ggpubr) # Configuraçõe de plots
require(ggthemes) # Temas diferentes para o ggplot
require(hrbrthemes) # Temas diferentes para o ggplot
require(viridis) # Para as paletas de cores
require(RPostgreSQL) # Conexão com o BD
require(lubridate) # Configuração de data e hora
require(stringr) # Edição de texto (Regex)
require(dplyr) # Organização de dados
require(scales)
Nesta sessãoo os dados são obtidos através de um link que foi extraído da inspeção da página do SIM. O link foi utilizado como base para criação de um loop para download dos dados. Os dados foram armazenados em um arquivo temporário, carregados e combinados a cada volta do loop.
A planilha obtida após combinar os dados foi utilizada para filtrar somente as variáveis de interesse, que foram descritas na introdução deste documento.
# Sequencia dos anos que serãoo baixados
anos <- seq(2015, 2018, by = 1)
# Cria um DF vazio para armazenar os resultados do loop
dados_combinados <- data.frame()
# Loop para baixar os dados
for(i in 1:length(anos)){
# Criação da URL
url <- paste0("https://s3-sa-east-1.amazonaws.com/ckan.saude.gov.br/SIM/Mortalidade_Geral_", anos[i] ,".csv")
# Download dos dados
download.file(url, destfile = "C:\\Users\\user\\Downloads\\temp.csv")
# Leitura e separação das colunas de interesse
dados <- read.csv2("C:\\Users\\user\\Downloads\\temp.csv")
head(dados)
dados <- dados[, c("DTOBITO","DTNASC","ESC","ESTCIV","HORAOBITO","IDADE","SEXO")]
# Combinar os dados
dados_combinados <- rbind(dados_combinados, dados)
# Remove o arquivo temporário após combinar a última planilha
file.remove("C:\\Users\\user\\Downloads\\temp.csv")
}
A seguir os dados serão configurados para que sejam identificados no formato correto. Foram feitas alterações nas colunas que continhas datas (DTOBITO e DTNASC), e a coluna IDADE foi separada em duas novas colunas, CODIDADE que contém os códigos que identificam a unidade de tempo da nova coluna VALIDADE que contém o número de unidades.
# Configurar as colunas de data - caso o dia contenha comente um dígito serão incluído um zero no início.
dados_combinados$DTOBITO <- ifelse(str_count(dados_combinados$DTOBITO) == 7, paste0("0",dados_combinados$DTOBITO), dados_combinados$DTOBITO)
dados_combinados$DTOBITO <- dmy(dados_combinados$DTOBITO)
dados_combinados$DTNASC <- ifelse(str_count(dados_combinados$DTNASC) == 7, paste0("0",dados_combinados$DTNASC), dados_combinados$DTNASC)
dados_combinados$DTNASC <- dmy(dados_combinados$DTNASC)
# Separa os dados da coluna idade em CODIDADE: código identificador da unidade de tempo, e em VALIDADE: número de unidades de tempo.
dados_combinados$CODIDADE <- as.integer(str_sub(dados_combinados$IDADE,1,1))
dados_combinados$VALIDADE <- as.integer(str_sub(dados_combinados$IDADE, 2))
# Excluir a antiga coluna idade
dados_combinados$IDADE <- NULL
# Configura os dados de hora
dados_combinados$HORAOBITO <- str_pad(dados_combinados$HORAOBITO, 4, pad = "0")
dados_combinados$HORAOBITO <- ifelse(!is.na(dados_combinados$HORAOBITO), paste0(str_sub(dados_combinados$HORAOBITO, start = 1, end = 2), ":", str_sub(dados_combinados$HORAOBITO, start = 3, end = 4)), "NA")
# Salvar os dados processados em um arquivo .csv para insersão no BD
write.csv(dados_combinados, file = 'C:\\InfraServer\\Backup\\DadosTratamento\\temp_comb.csv', row.names = F)
Os Códigos abaixo contém a criação do Banco de dados e a insersão dos dados que foram processados no bloco de código anterior. Os dados haviam sido salvos em um arquivo .csv temporário que é apagado ao final da insersão dos dados no BD.
# Configura a conexão com o BD
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, db = "postgres", user = "postgres", password = "postgres123", host = "localhost", port = 5432)
# Cria o Schema para armazenar as tabelas dos obitos e as tabelas com as categorias das variáveis
dbGetQuery(con, "DROP SCHEMA IF EXISTS obitos_brasil_sim CASCADE;")
dbGetQuery(con, "CREATE SCHEMA obitos_brasil_sim;")
# Cria a tabela com os dados dos óbitos
dbGetQuery(con, "CREATE TABLE obitos_brasil_sim.obitos(
DTOBITO timestamp without time zone,
DTNASC timestamp without time zone,
ESC integer,
ESTCIV integer,
HORAOBITO character(5),
SEXO integer,
CODIDADE integer,
VALIDADE integer
);")
dbGetQuery(con, "CREATE INDEX obitos_sexo
ON obitos_brasil_sim.obitos
USING btree (SEXO);")
dbGetQuery(con, "CREATE INDEX obitos_codidade
ON obitos_brasil_sim.obitos
USING btree (CODIDADE);")
dbGetQuery(con, "CREATE INDEX obitos_estciv
ON obitos_brasil_sim.obitos
USING btree (ESTCIV);")
dbGetQuery(con, "CREATE INDEX obitos_esc
ON obitos_brasil_sim.obitos
USING btree (ESC);")
dbDisconnect(con)
dbGetQuery(con, "COPY obitos_brasil_sim.obitos(
DTOBITO,DTNASC,ESC,ESTCIV,HORAOBITO,SEXO,CODIDADE,VALIDADE)
FROM 'C:\\InfraServer\\Backup\\DadosTratamento\\temp_comb.csv'
WITH (FORMAT csv, HEADER, DELIMITER ',', NULL 'NA');")
file.remove('C:\\InfraServer\\Backup\\DadosTratamento\\temp_comb.csv')
Abaixo serão criadas as tabelas que explicam as variávies categóricas. Os dados serão criados de acordo com a legenda fornecida no documento citado no início.
# Cria os dados dos niveis das variaveis categoricas.
escolaridade <- data.frame("ESC" = c(1,2,3,4,5,9), "ESC_NIVEL" = c("Nenhuma", "1 a 3 anos", "4 a 7 anos", "8 a 11 anos", "2 anos e mais", "Ignorado"))
est_civil <- data.frame("ESTCIV" = c(1,2,3,4,5,9), "ESTCIV_NIVEL" = c("Solteiro","Casado","Viuvo","Separado judicialmente","Uniao consensual","Ignorado"))
write.csv(escolaridade,'C:\\InfraServer\\Backup\\DadosTratamento\\escolaridade_temp.csv', row.names = F)
write.csv(est_civil,'C:\\InfraServer\\Backup\\DadosTratamento\\estacv_temp.csv', row.names = F)
# Configura a conexão com o BD
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, db = "postgres", user = "postgres", password = "postgres123", host = "localhost", port = 5432)
dbSendQuery(con, "DROP TABLE IF EXISTS obitos_brasil_sim.escolaridade CASCADE;")
dbSendQuery(con, "DROP TABLE IF EXISTS obitos_brasil_sim.estado_civil CASCADE;")
dbGetQuery(con, "CREATE TABLE obitos_brasil_sim.escolaridade(
ESC integer,
ESC_NIVEL varchar);")
dbGetQuery(con, "CREATE INDEX escolaridade_esc
ON obitos_brasil_sim.escolaridade
USING btree (esc);")
dbGetQuery(con, "COPY obitos_brasil_sim.escolaridade(
ESC, ESC_NIVEL)
FROM 'C:\\InfraServer\\Backup\\DadosTratamento\\escolaridade_temp.csv'
WITH (FORMAT csv, HEADER, DELIMITER ',', NULL 'NA');")
# Criar a tabela no banco de dados
dbGetQuery(con, "CREATE TABLE obitos_brasil_sim.estado_civil(
ESTCIV integer,
ESTCIV_NIVEL varchar);")
# Configurar a couna de index
dbGetQuery(con, "CREATE INDEX estado_civil_estciv
ON obitos_brasil_sim.estado_civil
USING btree (ESTCIV);")
# Inserir os dados no BD
dbGetQuery(con, "COPY obitos_brasil_sim.estado_civil(
ESTCIV, ESTCIV_NIVEL)
FROM 'C:\\InfraServer\\Backup\\DadosTratamento\\estacv_temp.csv'
WITH (FORMAT csv, HEADER, DELIMITER ',', NULL 'NA');")
# Apagar os dados temporários
file.remove('C:\\InfraServer\\Backup\\DadosTratamento\\escolaridade_temp.csv')
file.remove('C:\\InfraServer\\Backup\\DadosTratamento\\estacv_temp.csv')
# Desconectar do BD
dbDisconnect(con)
Nesta página os dados são selecionados do banco de dados de acordo com as relações entre as tabelas. A query de seleção foi copiada para um arquivo .csv que será utilziado para realizar as análises.
# Configura a conexão com o BD
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, db = "postgres", user = "postgres", password = "postgres123", host = "localhost", port = 5432)
# Executar a query para obter os dados do BD
dados_obitos <- dbGetQuery(con, "COPY (SELECT
DTOBITO,
DTNASC,
ESC_NIVEL,
ESTCIV_NIVEL,
HORAOBITO,
SEXO,
CODIDADE,
VALIDADE
FROM obitos_brasil_sim.estado_civil, obitos_brasil_sim.obitos, obitos_brasil_sim.escolaridade
WHERE estado_civil.ESTCIV = obitos.ESTCIV AND escolaridade.ESC = obitos.ESC) TO
'C:\\InfraServer\\Backup\\DadosTratamento\\select_temp.csv'
WITH CSV DELIMITER ',' HEADER;")
dbDisconnect(con)
Carregar o arquivo dos dados selecionados e vizualizar as primeiras linhas dos dados.
dados <- read.csv('C:\\InfraServer\\Backup\\DadosTratamento\\select_temp.csv')
dados$dtobito <- as.Date(dados$dtobito)
dados$dtnasc <- as.Date(dados$dtnasc)
dados$sexo <- ifelse(dados$sexo == 1, "Masculino", ifelse(dados$sexo == 2, "Feminino", "Indefinido"))
dados$idade_anos <- ifelse(dados$codidade < 4, 0,
ifelse(dados$codidade == 4, dados$validade,
ifelse(dados$codidade == 5, 100, NA)))
A exploração dos dados consiste em resumir os dados através de sumarios numéricos e visualizações gráficas. Esta sessão contém somente os códigos das figuras e dos resultados númericos obtidos, que serão apresentados na sessão de resultados.
Organização dos dados para a figura 1
# Sumariza os dados para os gráficos
resumo <- dados %>% group_by(sexo) %>% summarise(numero_mortes = length(sexo), idade = boxplot.stats(idade_anos)$stats)
resumo$legenda <- ifelse(resumo$idade == 100, "100+", resumo$idade)
resumo_geral <- dados %>% summarise(idade = boxplot.stats(idade_anos)$stats)
resumo_geral$legenda <- ifelse(resumo_geral$idade == 100, "100+", resumo_geral$idade)
resumo_mais_100 <- dados[dados$codidade == 5,] %>% group_by(sexo) %>% summarise(numero = length(sexo))
medias <- dados %>% group_by(sexo) %>% summarise(media = mean(idade_anos, na.rm = T))
media_idade <- mean(dados$idade_anos, na.rm = T)
resumo_idade <- dados %>%
group_by(sexo) %>%
summarise(numero_mortes = length(sexo), proporcao = paste0(round((length(sexo)/nrow(dados))*100, 2), "%"))
resumo_escolaridade <- dados %>%
group_by(esc_nivel, sexo) %>%
summarise(numero = length(esc_nivel), idade_media = round(mean(idade_anos, na.rm = T),2)) %>% filter(sexo != "Indefinido")
Código da figura 1.
# Plots que farão parte da figura
g1 <- ggplot(dados, aes(x = sexo, y = idade_anos, fill = sexo)) +
geom_boxplot() +
geom_text(data = resumo, aes(x = sexo, y = idade, label = legenda), position = position_dodge(1), vjust = 1) +
geom_point(data = medias, aes(x = sexo, y = media), col = "red") +
geom_text(data = medias, aes(x = sexo, y = media, label = round(media, 0)), col = "red", vjust = 1.2) +
scale_fill_viridis(discrete = T, alpha = 0.5, begin = 0.4) +
theme_ipsum() +
theme(
legend.position="none",
plot.title = element_text(size=11)
) +
ggtitle("Resumo das idades dos óbitos e diferênça entre sexos") +
xlab("") +
ylab("Idade (anos)")
g2 <- ggplot(dados, aes(x = "Geral", y = idade_anos, fill = "")) +
geom_boxplot() +
geom_text(data = resumo_geral, aes(x = "Geral", y = idade, label = legenda), position = position_dodge(1), vjust = 1) +
scale_fill_viridis(discrete = T, alpha = 0.5, begin = 0.8) +
theme_ipsum(grid = F, axis = F) +
theme(
legend.position="none",
plot.title = element_text(size=11),
axis.text.y = element_blank()
) +
ggtitle("Geral") +
ylab("") +
xlab("")
g3 <- ggplot(resumo_idade, aes(x= sexo, y = numero_mortes, fill = sexo)) +
geom_bar(stat = "identity") +
geom_text(aes(label = proporcao), vjust = 1.2) +
geom_text(aes(x = "Indefinido", y = numero_mortes[2], label = proporcao[2]), vjust = -1) +
scale_fill_viridis(discrete = T, alpha = 0.5, begin = 0.4) +
theme_ipsum(grid = F, axis = F) +
theme(
legend.position="none",
plot.title = element_text(size=11),
axis.text.y = element_blank()
) +
ggtitle("") +
ylab("") +
xlab("")
g4 <- ggplot() +
geom_text(aes(x = 1, y = 1, label = paste0("Total:\n", format(nrow(dados), big.mark = "."))), size = 8) +
theme_transparent()
figura1 <- ggarrange(ggarrange(g4, g3, ncol = 2, widths = c(0.7,2)),
ggarrange(g1, g2, ncol = 2, widths = c(2,0.7)),
nrow = 2, heights = c(1,2))
figura1 <- annotate_figure(figura1,
top = text_grob("Resumos das informações de idade e sexo dos óbitos no Brasil entre 2015 e 2018", size = 12, face = "bold"))
Organização dos dados e código da figura 2.
dados$ano <- year(dados$dtobito)
dados$mes <- month(dados$dtobito)
dados$anomes <- paste(dados$ano, str_pad(dados$mes, 2, pad = "0"), sep = "_")
resumo_ano_mes <- dados %>% group_by(anomes) %>% summarise(numero = length(mes))
resumo_ano_mes$fator <- as.numeric(as.factor(resumo_ano_mes$anomes))
resumo_ano_mes$ano <- str_sub(resumo_ano_mes$anomes, start = 1,end = 4)
resumo_ano_mes$mes <- str_sub(resumo_ano_mes$anomes, start = 6)
resumo_ano_mes$mes <- month(as.numeric(resumo_ano_mes$mes), label = T, locale = "Portuguese_Brazil.1252")
meses_mais <- resumo_ano_mes %>% group_by(ano) %>% top_n(1, numero)
meses_menos <- resumo_ano_mes %>% group_by(ano) %>% top_n(-1, numero)
figura2 <- ggplot(resumo_ano_mes, aes(x = fator, y = numero, group = ano)) +
geom_line() +
geom_point(data = meses_mais, aes(x = fator, y = numero), col = "red") +
geom_text(data = meses_mais, aes(x = fator, y = numero, label = mes), col = "red", vjust = -0.5) +
geom_point(data = meses_menos, aes(x = fator, y = numero), col = "blue") +
geom_text(data = meses_menos, aes(x = fator, y = numero, label = mes), col = "blue", vjust = 1) +
scale_x_continuous(breaks = resumo_ano_mes$fator, labels = resumo_ano_mes$mes) +
scale_y_continuous(n.breaks = 10) +
facet_grid(cols = vars(ano), scales = "free", space = "free") +
theme_few() +
theme(panel.spacing = unit(0, "lines"),
panel.border = element_rect(color = alpha("black", alpha = 0.05)),
strip.background = element_rect(colour = alpha("black", alpha = 0.05), fill = alpha("black", alpha = 0.05)),
strip.text = element_text(size = 12)) +
xlab("Mês") +
ylab("Número de mortos")
Foram registrados um total de 4610125 mortes no Brasil entre os anos de 2015 a 2018. Deste total 55.97% são pessoas do sexo masculino. A idade média geral de sobrevivência foi de 66.59 anos, sendo que os homens viveram em média até os 62.73 anos e as mulheres até os 71.48 anos. 50% das pessoas viveram entre 55 e 82 anos. O resumo das informações está apresentado gráficamente na Figura 1. O número de homens que sobreviveu por mais de 100 anos foi de 10449 e de mulheres foi de 24508.
Figura 1. Resumo das informações de sexo e idade das pessoas que morreram no Brasil entre 2015 e 2018.
O número de mortes teve variação mensal ao longo dos anos, porém foi possível encontrar um padrão nos números de mortes mensais ao longo dos anos. Os mês de fevereiro, em 3 dos 4 anos observados foi o mês que foi registrado o menos número de óbitos, já o mês de julho foi o mês que apresentou o maior número de óbitos também em 3 dos 4 anos observados (Figura 2).
Figura 2. Resumo das informações das mortes no Brasil entre os anos de 2015 e 2018. Foram destacados os meses que apresentaram os maiores e os menores números de mortes em cada ano.
Quanto ao número de anos de formação, o maior número de óbitos registrados é para pessoas que estudaram ente 1 e 7 anos. As pessoas que estudaram de 8 a 11 anos estão abaixo da média de idade de sobrevivênvia, tanto para homens quanto para mulheres. As mulheres sem nenhum registro de estudo foram as pessoas que apresentaram a maior idade média do óbito.
Tabela 1. Dados de níveis de anos de estudo, número de óbitos e idade média, divididos por sexo.| Anos de estudo | Sexo | Número de óbitos | Idade média |
|---|---|---|---|
| 1 a 3 anos | Feminino | 537772 | 74.07 |
| 1 a 3 anos | Masculino | 657443 | 66.38 |
| 2 anos e mais | Feminino | 101995 | 63.22 |
| 2 anos e mais | Masculino | 142179 | 64.02 |
| 4 a 7 anos | Feminino | 403367 | 68.37 |
| 4 a 7 anos | Masculino | 628636 | 58.09 |
| 8 a 11 anos | Feminino | 271290 | 62.59 |
| 8 a 11 anos | Masculino | 423775 | 55.15 |
| Ignorado | Feminino | 260199 | 71.97 |
| Ignorado | Masculino | 346638 | 62.68 |
| Nenhuma | Feminino | 454446 | 78.07 |
| Nenhuma | Masculino | 381632 | 72.09 |
Obs. As observações feitas a respeito dos dados são apenas para treinamento e não devem ser consideradas para tomadas de decisão e como dados oficiais.
.