A violência de gênero é uma realidade urgente e alarmante em Pernambuco. Ela ameaça não só a integridade física das vítimas, mas também seu bem-estar emocional, social e econômico. Cada registro no sistema de saúde representa mais que um número: ele revela histórias de agressões que exigem atenção e ações eficazes.
Utilizei os dados do SINAN – Sistema de Informação de Agravos de Notificação do Brasil, integrados com bases do Instituto Brasileiro de Geografia e Estatística (municípios-IBGE) e do Ministério da Saúde (CNES – Cadastro Nacional de Estabelecimentos de Saúde). A partir desses cruzamentos, é possível padronizar localidades e identificar as unidades notificadoras, trazendo maior precisão à análise.
Este estudo, desenvolvido no contexto de uma Iniciação Científica, explora os registros de violência notificados no estado entre 2023 e 2024. Devido a esse vínculo, algumas etapas de pré-processamento, como a conversão da idade codificada para a idade real e a tradução de variáveis categóricas, já foram estruturadas previamente, seguindo rigorosamente o Dicionário de Dados do SINAN.
A estratégia analítica adotada combina uma exploração descritiva — detalhando frequências por faixa etária, tipologia da violência, local de ocorrência e sexo — com a cartografia dos serviços de saúde que recebem essas notificações. O foco central é compreender os padrões, tendências e desigualdades presentes nos dados, fornecendo um diagnóstico robusto para gestores, pesquisadores e a sociedade civil.
Por fim, os insights gerados possuem o objetivo de apoiar a formulação de políticas de prevenção mais informadas, permitir um melhor direcionamento de recursos em saúde pública e fomentar debates sociais mais profundos sobre as dinâmicas da violência de gênero em Pernambuco.
A tabela abaixo lista as bibliotecas essenciais para a execução deste projeto, detalhando o propósito de cada uma:
| Nome.do.Pacote | Propósito |
|---|---|
| tidyverse | Manipulação, filtragem e visualização de dados (dplyr/ggplot2) |
| lubridate | Tratamento e conversão de datas |
| readxl | Importação de arquivos no formato Excel (.xlsx) |
| janitor | Limpeza automática de nomes de colunas e dados |
| geobr | Obtenção de dados geográficos do IBGE |
| sf | Análise e manipulação de dados geoespaciais (cartografia) |
| DT | Criação de tabelas HTML interativas |
| knitr | Geração de relatórios e tabelas no RMarkdown |
| stringi | Manipulação de texto e remoção de acentos (essencial para os mapas) |
Nesta etapa são carregados os bancos de dados (2023 e 2024), seguidos pelos processos de padronização, tratamento de datas, interpretação da idade real e integração das unidades notificadoras com a base do CNES.
Os dados utilizados neste trabalho são provenientes do Sistema de Informação de Agravos de Notificação (SINAN), disponibilizado pelo Ministério da Saúde via plataforma DATASUS (https://datasus.saude.gov.br/transferencia-de-arquivos/# ). O SINAN reúne notificações de agravos registradas por diferentes serviços de saúde em todo o país. Os arquivos originais correspondem aos anos de 2023 e 2024, fornecidos em formato DTB e contendo registros individuais de notificações de violência.
Como esses dados já haviam sido utilizados em minha Iniciação Científica, foi realizada previamente a conversão dos arquivos DTB para o formato .xlsx, preservando a estrutura original. É importante destacar que o propósito do SINAN é a vigilância epidemiológica, e não a produção de bases otimizadas para análises estatísticas — o que exige cuidados adicionais na etapa de limpeza.
Cada arquivo possui dezenas de variáveis relacionadas a:
Datas: notificação, ocorrência e outras.
Informações demográficas: idade, sexo e municípios de residência/notificação.
Características da violência: tipo, meio, relação com o agressor e local.
Campos administrativos: códigos e informações próprias do SINAN.
Os dados apresentam particularidades típicas de sistemas de vigilância, como valores ausentes (células vazias ou códigos como 99 – Ignorado), inconsistências temporais (ex.: notificação posterior à ocorrência), variações de categorias entre anos e nomes de colunas com acentos ou formatação diferente, exigindo padronização.
Diante disso, a etapa de preparação torna-se essencial. Nesta fase, realizou-se a importação dos arquivos, a união das bases de 2023 e 2024, a padronização dos nomes das variáveis, o tratamento das datas e a correção das inconsistências necessárias para garantir a qualidade analítica dos dados.
A primeira etapa consiste em carregar os arquivos referentes a 2023 e 2024. Utilizou-se a função read_excel() (pacote readxl) para a leitura dos arquivos .xlsx.
Durante a importação, definiu-se explicitamente o argumento col_types = “text”. Essa medida é crucial ao lidar com dados do SINAN para evitar erros de incompatibilidade de tipos entre os anos (por exemplo, quando uma coluna é interpretada como número em um arquivo e texto no outro) e para preservar a integridade dos códigos identificadores (mantendo zeros à esquerda).
Optou-se por manter os nomes das variáveis em seu formato original (caixa alta), sem a aplicação imediata de funções de padronização de nomenclatura (como clean_names), para assegurar a compatibilidade direta com o Dicionário de Dados oficial do SINAN nas etapas de tradução subsequentes.
Após a leitura, realizou-se a união das bases com dplyr::bind_rows(), formando um único conjunto consolidado de notificações brutas.
# Lista contendo cada ano da base
dados_sinan_lista <- list(
readxl::read_excel("sinan_2023.xlsx", col_types = "text"),
readxl::read_excel("sinan_2024.xlsx", col_types = "text")
)
# União dos bancos de 2023 e 2024
dados_sinan <- dplyr::bind_rows(dados_sinan_lista)
# Visualização de exemplo
DT::datatable(
dados_sinan[1:10, c("DT_NOTIFIC", "ID_MUNICIP", "ID_UNIDADE",
"DT_OCOR", "IDADE", "SEXO")],
caption = "Amostra das 10 primeiras linhas da base SINAN (variáveis-chave)",
options = list(pageLength = 10, dom = 'tip')
)Como os dados brutos do SINAN utilizam códigos numéricos para representar categorias (ex.: “1” para “Sim”, “2” para “Não”, ou códigos específicos para locais e motivações), foi necessário realizar um processo de tradução para tornar a base legível e analiticamente útil.
Utilizando como referência o Dicionário de Dados do SINAN (Versão 5), construímos “mapas” (vetores nomeados) no R para associar cada código à sua respectiva descrição. Esse processo envolveu três estratégias principais implementadas via pacote tidyverse:
Criação de Dicionários de Tradução: Foram definidos vetores para mapear categorias gerais (como variáveis binárias de “Sim/Não/Ignorado”) e categorias específicas (como LOCAL_OCOR, VIOL_MOTIV, ORIENT_SEX, etc.). Nesta etapa, também houve padronização de inconsistências de formatação presentes nos arquivos originais (ex.: unificando os códigos “1” e “01” para a mesma categoria).
Padronização dos Tipos de Dados: Antes da tradução, todas as colunas foram convertidas para o tipo texto (character). Isso foi necessário para garantir que a função de recodificação funcionasse uniformemente, evitando erros decorrentes de colunas interpretadas como numéricas em um ano e texto no outro.
Substituição dos Códigos: Utilizando as funções mutate(), across() e recode(), aplicamos as traduções diretamente nas colunas originais.
Para as mais de 50 variáveis binárias (como VIOL_FISIC, REL_PAI, ENC_SAUDE), a tradução foi aplicada em massa.
Para variáveis com categorias únicas (como Local de Ocorrência e Motivação), a recodificação foi aplicada individualmente conforme os dicionários específicos.
library(tidyverse)
# tradução dos códigos da planilha
mapa_sim_nao <- c("1"="Sim", "2"="Não", "8"="Não se aplica", "9"="Ignorado", "99"="Ignorado")
mapa_local <- c("01"="Residência", "1"="Residência", "02"="Habitação Coletiva", "2"="Habitação Coletiva",
"03"="Escola", "3"="Escola", "04"="Local prática esportiva", "4"="Local prática esportiva",
"05"="Bar ou similar", "5"="Bar ou similar", "06"="Via pública", "6"="Via pública",
"07"="Comércio/Serviços", "7"="Comércio/Serviços", "08"="Indústria/Construção", "8"="Indústria/Construção",
"09"="Outro", "9"="Outro", "99"="Ignorado")
mapa_orientacao <- c("1"="Heterossexual", "2"="Homossexual (gay/lésbica)", "3"="Bissexual", "8"="Não se aplica", "9"="Ignorado")
mapa_genero <- c("1"="Travesti", "2"="Transexual mulher", "3"="Transexual homem", "8"="Não se aplica", "9"="Ignorado")
mapa_motivacao <- c("01"="Sexismo", "1"="Sexismo", "02"="Homofobia/Lesbofobia/Transfobia", "2"="Homofobia/Lesbofobia/Transfobia",
"03"="Racismo", "3"="Racismo", "04"="Intolerância religiosa", "4"="Intolerância religiosa",
"05"="Xenofobia", "5"="Xenofobia", "06"="Conflito geracional", "6"="Conflito geracional",
"07"="Situação de rua", "7"="Situação de rua", "08"="Deficiência", "8"="Deficiência",
"09"="Outros", "9"="Outros", "88"="Não se aplica", "99"="Ignorado")
mapa_ciclo_vida <- c("1"="Criança (0-9)", "2"="Adolescente (10-19)", "3"="Jovem (20-24)", "4"="Adulto (25-59)", "5"="Idoso (60+)", "9"="Ignorado")
mapa_autor_sexo <- c("1"="Masculino", "2"="Feminino", "3"="Ambos", "9"="Ignorado")
mapa_num_envolv <- c("1"="Um", "2"="Dois ou mais", "9"="Ignorado")
# colunas que possuem "sim/não"
cols_sim_nao <- c(
"DEF_TRANS", "DEF_FISICA", "DEF_MENTAL", "DEF_VISUAL", "DEF_AUDITI", "TRAN_MENT",
"VIOL_FISIC", "VIOL_PSICO", "VIOL_TORT", "VIOL_SEXU", "VIOL_TRAF",
"VIOL_FINAN", "VIOL_NEGLI", "VIOL_INFAN",
"AG_FORCA", "AG_ENFOR", "AG_OBJETO", "AG_CORTE", "AG_QUENTE",
"AG_ENVEN", "AG_FOGO", "AG_AMEACA",
"SEX_ASSEDI", "SEX_ESTUPR", "SEX_PORNO", "SEX_EXPLO",
"REL_PAI", "REL_MAE", "REL_PAD", "REL_MAD", "REL_CONJ", "REL_EXCON",
"REL_NAMO", "REL_EXNAM", "REL_IRMAO", "REL_FILHO", "REL_CONHEC",
"REL_DESCO", "REL_DESCO.1", "REL_PATRAO", "REL_INST", "REL_POL", "REL_TRAB",
"ENC_SAUDE", "ASSIST_SOC", "REDE_EDUCA", "ATEND_MULH", "CONS_TUTEL",
"CONS_IDO", "DIR_HUMAN", "MPU", "DELEG_CRIA", "DELEG_MULH",
"INFAN_JUV", "DEFEN_PUBL", "DELEG_IDOS"
)
# aplicação das traduções
dados_tratados <- dados_sinan |>
mutate(
across(everything(), as.character),
# traduz colunas de Sim/Não
across(any_of(cols_sim_nao), ~recode(., !!!mapa_sim_nao)),
# traduz as específicas (atribuindo ao mesmo nome original)
LOCAL_OCOR = recode(LOCAL_OCOR, !!!mapa_local),
ORIENT_SEX = recode(ORIENT_SEX, !!!mapa_orientacao),
IDENT_GEN = recode(IDENT_GEN, !!!mapa_genero),
VIOL_MOTIV = recode(VIOL_MOTIV, !!!mapa_motivacao),
CICL_VID = recode(CICL_VID, !!!mapa_ciclo_vida),
AUTOR_SEXO = recode(AUTOR_SEXO, !!!mapa_autor_sexo),
NUM_ENVOLV = recode(NUM_ENVOLV, !!!mapa_num_envolv)
)
# Visualização
DT::datatable(
head(dados_tratados |> select(DT_NOTIFIC, VIOL_FISIC, LOCAL_OCOR, VIOL_MOTIV)),
caption = "Base com Códigos Substituídos por Nomes",
options = list(dom = 't')
)Para garantir a integridade da análise, realizou-se primeiro a padronização dos campos vazios, convertendo células sem informação para o código NA.
Em seguida, aplicou-se um critério de exclusão seletiva: foram removidos da base apenas os registros que não possuíam informações essenciais para a identificação do caso, especificamente a Data de Notificação (DT_NOTIFIC) e o Município de Notificação (ID_MUNICIP). Para as demais variáveis descritivas (como raça ou motivação), optou-se por manter os dados ausentes, que serão categorizados como “Ignorado” nas análises subsequentes.
# Lista de colunas de interesse
cols_limpeza <- c(
"DT_NOTIFIC", "ESTADO_NOTIFICACAO", "NU_ANO", "ID_MUNICIP", "ID_UNIDADE",
"DT_OCOR", "ANO_NASC", "IDADE", "SEXO", "CS_RACA", "SG_UF", "ID_MUNIC_RESI",
"ID_MN_OCOR", "LOCAL_OCOR", "ORIENT_SEX", "IDENT_GEN", "DEF_TRANS",
"DEF_FISICA", "DEF_MENTAL", "DEF_VISUAL", "DEF_AUDITI", "TRAN_MENT",
"VIOL_MOTIV", "VIOL_FISIC", "VIOL_PSICO", "VIOL_TORT", "VIOL_SEXU",
"VIOL_TRAF", "VIOL_FINAN", "VIOL_NEGLI", "VIOL_INFAN", "AG_FORCA",
"AG_ENFOR", "AG_OBJETO", "AG_CORTE", "AG_QUENTE", "AG_ENVEN", "AG_FOGO",
"AG_AMEACA", "SEX_ASSEDI", "SEX_ESTUPR", "SEX_PORNO", "SEX_EXPLO",
"NUM_ENVOLV", "AUTOR_SEXO", "CICL_VID", "REL_PAI", "REL_MAE", "REL_PAD",
"REL_MAD", "REL_CONJ", "REL_EXCON", "REL_NAMO", "REL_EXNAM", "REL_IRMAO",
"REL_FILHO", "REL_CONHEC", "REL_DESCO", "REL_DESCO.1", "REL_PATRAO",
"REL_INST", "REL_POL", "ENC_SAUDE", "ASSIST_SOC", "REDE_EDUCA",
"ATEND_MULH", "CONS_TUTEL", "CONS_IDO", "DIR_HUMAN", "MPU", "DELEG_CRIA",
"DELEG_MULH", "INFAN_JUV", "DEFEN_PUBL", "DELEG_IDOS", "REL_TRAB"
)
dados_finais <- dados_tratados |>
# padronizar: Transformar vazio ("") e espaço (" ") em NA
mutate(
across(any_of(cols_limpeza), ~na_if(., "")),
across(any_of(cols_limpeza), ~na_if(., " "))
) |>
# filtro para remover apenas se faltar Data ou Município
drop_na(DT_NOTIFIC, ID_MUNICIP)
# Visualizar o resultado
DT::datatable(head(dados_finais), options = list(scrollX = TRUE, dom = 't'))Nesta seção, investigamos os padrões da violência notificada em sua totalidade, buscando compreender as diferenças demográficas, as características das agressões e a distribuição espacial dos casos em Pernambuco, com ênfase nas disparidades de gênero e raça.
Esta seção estabelece a dimensão quantitativa do problema. Analisamos o volume total de notificações registradas no período, comparando a evolução entre 2023 e 2024.
# meses para garantir ordem correta
meses_pt <- c("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
"Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro")
# colunas auxiliares
dados_tempo <- dados_finais |>
filter(!is.na(DT_NOTIFIC)) |>
mutate(
DT_NOTIFIC = lubridate::ymd(DT_NOTIFIC),
ANO = year(DT_NOTIFIC),
MES_NUM = month(DT_NOTIFIC),
MES = factor(MES_NUM, levels = 1:12, labels = meses_pt, ordered = TRUE)
)
# tabela
tabela_ano <- dados_tempo |>
count(ANO, name = "Total de Casos") |>
mutate(
Variação = (`Total de Casos` - lag(`Total de Casos`)) / lag(`Total de Casos`),
Variação_Formatada = scales::percent(Variação, accuracy = 0.1)
)
print(knitr::kable(tabela_ano, caption = "Total de Notificações de Violência por Ano em PE"))##
##
## Table: Total de Notificações de Violência por Ano em PE
##
## | ANO| Total de Casos| Variação|Variação_Formatada |
## |----:|--------------:|----------:|:------------------|
## | 2023| 4135| NA|NA |
## | 2024| 2943| -0.2882709|-28.8% |
# grafico de barras
ggplot(dados_tempo, aes(x = factor(ANO))) +
geom_bar(fill = "#2C3E50", width = 0.6) +
geom_text(stat='count', aes(label=..count..), vjust=-0.5, fontface="bold", size=5) +
labs(title = "Volume de Notificações por Ano",
subtitle = "Comparativo absoluto (2023 vs 2024)",
x = "Ano de Notificação",
y = "Quantidade de Casos") +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
panel.grid.major.x = element_blank()
) +
ylim(0, max(table(dados_tempo$ANO)) * 1.15)Ao observar a distribuição mensal, buscamos padrões sazonais. Picos em meses específicos podem estar associados a festividades (como Carnaval ou São João) ou campanhas de conscientização (como o Março Mulher)
# agrupando dados por Mês e Ano
dados_mensal <- dados_tempo |>
count(ANO, MES) |>
mutate(ANO = factor(ANO))
# Gráfico de Linhas
ggplot(dados_mensal, aes(x = MES, y = n, group = ANO, color = ANO)) +
geom_line(linewidth = 1.2, alpha = 0.8) +
geom_point(size = 3) +
scale_color_manual(values = c("2023" = "#95A5A6", "2024" = "#C0392B")) +
labs(title = "Evolução Mensal das Notificações",
subtitle = "Comparativo de sazonalidade e tendência mensal",
x = "",
y = "Número de Notificações",
color = "Ano") +
theme_minimal() +
theme(
legend.position = "top",
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank()
)
A análise temporal revela um comportamento distinto entre os dois anos.
Observa-se que, durante o primeiro semestre (janeiro a junho), o ano de
2024 (linha vermelha) apresentou sistematicamente um volume de
notificações superior ao registrado em 2023 (linha cinza), indicando uma
tendência de crescimento dos registros no estado.
Entretanto, nota-se uma queda abrupta nas notificações de 2024 a partir de setembro. Este fenômeno não deve ser interpretado como redução real da violência, pois, considerando que o SINAN segue um fluxo hierárquico de transmissão (Unidade > Município > Estado > Federal), é esperado que os meses mais recentes da base de dados atual (2024) ainda não estejam totalmente consolidados. Portanto, a redução visualizada no gráfico deve ser interpretada com cautela, tratando-se provavalmente de dados preliminares e não de uma diminuição real da violência no período.
Compreender o perfil das vítimas é essencial para identificar grupos de vulnerabilidade e direcionar políticas públicas. Nesta seção, detalhamos a distribuição dos casos por sexo, raça/cor e ciclo de vida.
Preparação demográfica
mapa_sexo <- c("M" = "Masculino", "F" = "Feminino", "I" = "Ignorado")
dados_demo <- dados_finais |>
mutate(
# garantia que o sexo que esteja como Masculino/Feminino
SEXO_DESC = recode(SEXO, !!!mapa_sexo, .default = SEXO),
# os vazios estão "Ignorado"
RACA_COR = if_else(is.na(CS_RACA) | CS_RACA == "", "Ignorado", CS_RACA),
# idade
IDADE_REAL = case_when(
# se tiver escrito "mês", "dia" ou "hora", é bebê -> 0 anos
str_detect(tolower(IDADE), "mês|mes|dia|hora") ~ 0,
# Se tiver escrito "ano", extrai só o número
str_detect(tolower(IDADE), "ano") ~ readr::parse_number(IDADE),
# se for só número (ex: "13"), converte direto
TRUE ~ as.numeric(IDADE)
),
# criação de faixas etárias
FAIXA_ETARIA = case_when(
IDADE_REAL < 10 ~ "Criança (0-9)",
IDADE_REAL >= 10 & IDADE_REAL < 20 ~ "Adolescente (10-19)",
IDADE_REAL >= 20 & IDADE_REAL < 60 ~ "Adulto (20-59)",
IDADE_REAL >= 60 ~ "Idoso (60+)",
TRUE ~ "Ignorado"
),
FAIXA_ETARIA = factor(FAIXA_ETARIA,
levels = c("Criança (0-9)", "Adolescente (10-19)",
"Adulto (20-59)", "Idoso (60+)", "Ignorado"))
)Raça e sexo: Análise interssecional
# Filtrando dados
dados_raca <- dados_demo |>
filter(SEXO_DESC %in% c("Feminino", "Masculino"),
RACA_COR != "Ignorado") |>
count(SEXO_DESC, RACA_COR)
# Gráfico
ggplot(dados_raca, aes(x = SEXO_DESC, y = n, fill = RACA_COR)) +
geom_col(position = "dodge") +
geom_text(aes(label = n), position = position_dodge(width = 0.9),
vjust = -0.5, size = 3, fontface = "bold") +
scale_fill_brewer(palette = "Set2") +
labs(title = "Distribuição de Raça/Cor por Sexo",
x = "", y = "Número de Casos", fill = "Raça/Cor") +
theme_minimal() +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", size = 14))
Análise com Faixas Etárias
dados_demo |>
filter(FAIXA_ETARIA != "Ignorado") |>
count(FAIXA_ETARIA) |>
ggplot(aes(x = fct_rev(FAIXA_ETARIA), y = n)) +
geom_col(fill = "#8E44AD", width = 0.7) +
geom_text(aes(label = n), hjust = -0.2, fontface = "bold") +
coord_flip() +
labs(title = "Notificações por Ciclo de Vida",
x = "", y = "Quantidade de Casos") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 14)) +
ylim(0, nrow(dados_demo) * 0.6)
Pirâmide Etária
cores_sexo <- c("Masculino" = "#2980B9", "Feminino" = "#C0392B")
dados_piramide <- dados_demo |>
filter(!is.na(IDADE_REAL), SEXO_DESC %in% c("Masculino", "Feminino")) |>
mutate(IDADE_BIN = cut(IDADE_REAL, breaks = seq(0, 100, 5), right = FALSE)) |>
count(SEXO_DESC, IDADE_BIN) |>
mutate(n_plot = ifelse(SEXO_DESC == "Masculino", -n, n))
ggplot(dados_piramide, aes(x = IDADE_BIN, y = n_plot, fill = SEXO_DESC)) +
geom_col(width = 0.9) +
coord_flip() +
scale_y_continuous(labels = abs,
limits = c(min(dados_piramide$n_plot, na.rm=TRUE)*1.1,
max(dados_piramide$n_plot, na.rm=TRUE)*1.1)) +
scale_fill_manual(values = cores_sexo) +
labs(title = "Pirâmide Etária da Violência",
x = "Faixa Etária (5 em 5 anos)",
y = "Número de Notificações",
fill = "") +
theme_minimal() +
theme(legend.position = "top",
plot.title = element_text(face = "bold", size = 14))O gráfico revela uma acentuada assimetria de gênero. O volume de notificações do sexo feminino (em vermelho) supera expressivamente o masculino (em azul) em quase todas as faixas etárias, confirmando o perfil da violência de gênero no estado.
Observa-se um padrão crítico para as mulheres a partir da faixa de 10 a 14 anos, com picos elevados durante toda a idade adulta jovem (até os 39 anos). Este comportamento sugere uma forte correlação com a violência doméstica, sexual e por parceiro íntimo, que se intensifica a partir da adolescência. Já na base da pirâmide (0 a 9 anos), a distribuição entre os sexos é mais equilibrada, indicando que, nesta fase, a violência (geralmente negligência ou física) atinge meninos e meninas de forma mais similar.
Além de identificar a vítima, é necessário entender a natureza da agressão.
Tipos de Violência
# preparação dos dados
dados_tipos <- dados_finais |>
filter(SEXO %in% c("Masculino", "Feminino", "M", "F")) |>
mutate(SEXO_GRAFICO = case_when(
str_starts(SEXO, "M") ~ "Masculino",
str_starts(SEXO, "F") ~ "Feminino",
TRUE ~ SEXO
)) |>
select(SEXO_GRAFICO, starts_with("VIOL_"), -VIOL_MOTIV) |>
pivot_longer(cols = -SEXO_GRAFICO, names_to = "TIPO", values_to = "RESPOSTA") |>
filter(RESPOSTA %in% c("Sim", "1")) |>
mutate(
TIPO = str_remove(TIPO, "VIOL_"),
TIPO = case_when(
TIPO == "FISIC" ~ "Física",
TIPO == "PSICO" ~ "Psicológica",
TIPO == "SEXU" ~ "Sexual",
TIPO == "NEGLI" ~ "Negligência/Abandono",
TIPO == "TORT" ~ "Tortura",
TIPO == "FINAN" ~ "Financeira",
TIPO == "TRAF" ~ "Tráfico Humano",
TIPO == "INFAN" ~ "Violência Infantil",
TRUE ~ TIPO
)
)
# grafico
ggplot(dados_tipos, aes(x = fct_infreq(TIPO), fill = SEXO_GRAFICO)) +
geom_bar(position = "dodge", width = 0.8, color = "white") +
coord_flip() +
scale_fill_manual(values = c("Masculino" = "#A9CCE3", "Feminino" = "#F5B7B1")) +
labs(title = "Tipos de Violência mais Notificados",
subtitle = "Comparativo por Gênero",
x = "",
y = "Quantidade de Notificações",
fill = "") +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(face = "bold", size = 14),
axis.text.y = element_text(size = 11)
)Meios de Agressão
dados_meios <- dados_finais |>
filter(SEXO %in% c("Masculino", "Feminino", "M", "F")) |>
mutate(SEXO_GRAFICO = case_when(
str_starts(SEXO, "M") ~ "Masculino",
str_starts(SEXO, "F") ~ "Feminino",
TRUE ~ SEXO
)) |>
select(SEXO_GRAFICO, starts_with("AG_")) |>
pivot_longer(cols = -SEXO_GRAFICO, names_to = "MEIO", values_to = "RESPOSTA") |>
filter(RESPOSTA %in% c("Sim", "1")) |>
mutate(
MEIO = str_remove(MEIO, "AG_"),
MEIO = case_when(
MEIO == "FORCA" ~ "Força Corporal",
MEIO == "ENFOR" ~ "Enforcamento",
MEIO == "OBJETO" ~ "Objeto Contundente",
MEIO == "CORTE" ~ "Perfurocortante",
MEIO == "QUENTE" ~ "Substância Quente",
MEIO == "ENVEN" ~ "Envenenamento",
MEIO == "FOGO" ~ "Arma de Fogo",
MEIO == "AMEACA" ~ "Ameaça",
TRUE ~ MEIO
)
)
# grafico
ggplot(dados_meios, aes(x = fct_infreq(MEIO), fill = SEXO_GRAFICO)) +
geom_bar(position = "stack", width = 0.7) +
scale_fill_manual(values = c("Masculino" = "#A9CCE3", "Feminino" = "#F5B7B1")) +
labs(title = "Meios de Agressão Utilizados",
subtitle = "Volume total por instrumento",
x = "",
y = "Total de Ocorrências",
fill = "") +
theme_minimal() +
theme(
legend.position = "top",
axis.text.x = element_text(angle = 45, hjust = 1)
)Nesta etapa, foi analisada o local onde a agressão ocorreu e o vínculo entre a vítima e o provável autor, dados essenciais para distinguir a violência doméstica daquela urbana ou comunitária.
Local da Violência
O gráfico abaixo compara os locais de ocorrência.
# escolhi 5 locais mais frequentes para limpar o gráfico
top_locais <- dados_finais |>
filter(SEXO %in% c("Masculino", "Feminino", "M", "F")) |>
count(LOCAL_OCOR, sort = TRUE) |>
slice(1:5) |>
pull(LOCAL_OCOR)
dados_local <- dados_finais |>
filter(LOCAL_OCOR %in% top_locais,
SEXO %in% c("Masculino", "Feminino", "M", "F")) |>
mutate(SEXO_GRAFICO = case_when(
str_starts(SEXO, "M") ~ "Masculino",
str_starts(SEXO, "F") ~ "Feminino",
TRUE ~ SEXO
))
# gráfico
ggplot(dados_local, aes(x = fct_infreq(LOCAL_OCOR), fill = SEXO_GRAFICO)) +
geom_bar(position = "dodge", width = 0.8, color = "white") +
scale_fill_manual(values = c("Masculino" = "#A9CCE3", "Feminino" = "#F5B7B1")) +
labs(title = "Local de Ocorrência da Violência",
subtitle = "Espaço público vs. Espaço privado",
x = "",
y = "Quantidade de Casos",
fill = "") +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(face = "bold", size = 14),
axis.text.x = element_text(size = 11)
)
Perfil do Agressor: Qual era o vínculo com a
vítima?
# preparação dos dados
dados_vinculo <- dados_finais |>
mutate(
SEXO_GRAFICO = case_when(
str_starts(SEXO, "M") | SEXO == "1" ~ "Vítimas: Homens",
str_starts(SEXO, "F") | SEXO == "2" ~ "Vítimas: Mulheres",
TRUE ~ NA_character_
)
) |>
filter(!is.na(SEXO_GRAFICO)) |>
mutate(
VINCULO_RESUMO = case_when(
REL_CONJ %in% c("Sim", "1") | REL_NAMO %in% c("Sim", "1") ~ "Parceiro Íntimo",
REL_EXCON %in% c("Sim", "1") | REL_EXNAM %in% c("Sim", "1") ~ "Ex-Parceiro",
REL_PAI %in% c("Sim", "1") | REL_MAE %in% c("Sim", "1") |
REL_PAD %in% c("Sim", "1") | REL_MAD %in% c("Sim", "1") ~ "Pais/Padrastos",
REL_FILHO %in% c("Sim", "1") | REL_IRMAO %in% c("Sim", "1") ~ "Irmão/Filho",
REL_CONHEC %in% c("Sim", "1") ~ "Amigo/Conhecido",
REL_PATRAO %in% c("Sim", "1") | REL_TRAB %in% c("Sim", "1") ~ "Patrão/Colega",
REL_POL %in% c("Sim", "1") ~ "Policial/Agente",
REL_DESCO %in% c("Sim", "1") ~ "Desconhecido",
TRUE ~ NA_character_
)
) |>
filter(!is.na(VINCULO_RESUMO))
# grafico
ggplot(dados_vinculo, aes(x = fct_infreq(VINCULO_RESUMO), fill = SEXO_GRAFICO)) +
geom_bar(width = 0.7, show.legend = FALSE) +
coord_flip() +
# Separa em dois gráficos lado a lado
facet_wrap(~SEXO_GRAFICO, scales = "free_x") +
scale_fill_manual(values = c("Vítimas: Homens" = "#A9CCE3", "Vítimas: Mulheres" = "#F5B7B1")) +
labs(title = "Quem comete a violência?",
subtitle = "Perfil do agressor segundo o sexo da vítima",
x = "",
y = "Número de Notificações") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
strip.text = element_text(face = "bold", size = 12), # Aumenta o título de cada painel
axis.text.y = element_text(size = 10)
)Número de envolvidos
dados_finais |>
filter(SEXO %in% c("Masculino", "Feminino", "M", "F"),
!is.na(NUM_ENVOLV), NUM_ENVOLV != "Ignorado") |>
mutate(SEXO_GRAFICO = case_when(str_starts(SEXO, "M") ~ "Masculino", TRUE ~ "Feminino")) |>
ggplot(aes(x = NUM_ENVOLV, fill = SEXO_GRAFICO)) +
geom_bar(position = "fill", width = 0.6) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("Masculino" = "#A9CCE3", "Feminino" = "#F5B7B1")) +
labs(title = "Agressão Individual vs. Coletiva",
subtitle = "Proporção de casos com um ou mais agressores",
x = "Número de Envolvidos",
y = "Proporção (%)",
fill = "") +
theme_minimal()Além de saber quem são as vítimas e onde ocorrem os casos, é fundamental entender quando a violência acontece. Investigamos a distribuição das notificações ao longo dos dias da semana para identificar padrões comportamentais associados ao lazer, ao consumo de álcool e à convivência familiar.
Dia da semana
O gráfico abaixo apresenta a curva de notificações de domingo a sábado. Picos aos finais de semana são fortes indicativos de violência associada ao convívio social ou doméstico intensificado.
# preparação com DT_OCOR (Ocorrência) para ver quando a violência aconteceu de fato
dados_temporal <- dados_finais |>
filter(!is.na(DT_OCOR)) |>
mutate(
SEXO_GRAFICO = case_when(
str_starts(SEXO, "M") | SEXO == "1" ~ "Masculino",
str_starts(SEXO, "F") | SEXO == "2" ~ "Feminino",
TRUE ~ NA_character_
)
) |>
filter(!is.na(SEXO_GRAFICO)) |>
mutate(
# dia da semana como fator
DIA_SEMANA = wday(DT_OCOR, label = TRUE, abbr = FALSE, week_start = 1),
# fator Fim de Semana
TIPO_DIA = case_when(
DIA_SEMANA %in% c("sábado", "domingo") ~ "Final de Semana",
TRUE ~ "Dia Útil"
)
)
# grafico
dados_temporal |>
count(DIA_SEMANA, SEXO_GRAFICO) |>
ggplot(aes(x = DIA_SEMANA, y = n, group = SEXO_GRAFICO, color = SEXO_GRAFICO)) +
geom_line(linewidth = 1.5, alpha = 0.8) +
geom_point(size = 4) +
scale_color_manual(values = c("Masculino" = "#76D7C4", "Feminino" = "#C39BD3")) +
labs(title = "Quando a violência acontece?",
subtitle = "Ocorrências por dia da semana (Data do Fato)",
x = "",
y = "Número de Casos",
color = "") +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(face = "bold", size = 14),
panel.grid.minor = element_blank(),
axis.text.x = element_text(size = 11)
)Fim de semana vs. Dia útil
# Gráfico
# usando dados_temporal (anterior)
ggplot(dados_temporal, aes(x = TIPO_DIA, fill = SEXO_GRAFICO)) +
geom_bar(position = "dodge", width = 0.6, color = "white") +
scale_fill_manual(values = c("Masculino" = "#76D7C4", "Feminino" = "#C39BD3")) +
labs(title = "Violência: Dias Úteis vs. Final de Semana",
subtitle = "Comparativo de volume de notificações (Data da Ocorrência)",
x = "",
y = "Total de Ocorrências",
fill = "") +
theme_minimal() +
theme(
legend.position = "top",
plot.title = element_text(face = "bold", size = 14),
axis.text.x = element_text(size = 12, face = "bold")
)
Os dados demonstram que, embora os dias úteis acumulem um volume
absoluto considerável de registros, a densidade de violência
(intensidade por dia) é significativamente maior aos finais de semana.
Observa-se uma escalada de ocorrências que se inicia nas sextas-feiras e
atinge seu ápice aos sábados e domingos. Este comportamento sugere uma
forte correlação entre a violência e momentos de convivência familiar
intensificada e atividades de lazer, frequentemente associados ao
consumo de álcool.
Utilizando técnicas de geoprocessamento, irei mapear a concentração de casos pelos municípios de Pernambuco. Esta visualização permite identificar as áreas de maior incidência e apoiar a distribuição de recursos considerando as especificidades regionais.
Mapa de calor
library(geobr)
library(stringi)
# baixar Mapa
mapa_pe <- geobr::read_municipality(code_muni = "PE", year = 2020, showProgress = FALSE)
# padronização
mapa_tratado <- mapa_pe |>
mutate(CHAVE = name_muni |> toupper() |> stri_trans_general("Latin-ASCII"))
dados_geo <- dados_finais |>
filter(!is.na(ID_MUNICIP)) |>
mutate(CHAVE = as.character(ID_MUNICIP) |> toupper() |> stri_trans_general("Latin-ASCII")) |>
count(CHAVE, name = "Total_Casos")
# merge
mapa_final <- mapa_tratado |>
left_join(dados_geo, by = "CHAVE") |>
# substitui NA por 0 para não ficar buraco no mapa
mutate(Total_Casos = replace_na(Total_Casos, 0))
# plot
ggplot(mapa_final) +
geom_sf(aes(fill = Total_Casos), color = "white", size = 0.1) +
# Escala de cor Logarítmica
scale_fill_viridis_c(option = "rocket", direction = -1,
name = "Casos",
trans = "log10",
labels = scales::comma) +
labs(title = "Distribuição Espacial da Violência em PE",
subtitle = "Volume total de notificações (2023-2024)",
caption = "Fonte: SINAN/DATASUS | Elaboração própria") +
theme_void() +
theme(
legend.position = "bottom",
plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5, color = "grey30")
)O mapa de calor evidencia uma forte concentração de notificações na faixa litorânea, correspondente à Região Metropolitana do Recife (RMR), área de maior densidade demográfica do estado.
Entretanto, a interiorização da violência é visível através dos polos regionais. Municípios-chave como Caruaru (Agreste) e Petrolina (Sertão do São Francisco) destacam-se como hotspots de notificação fora da capital. As áreas mais claras podem indicar municípios com menor população ou, em alguns casos, onde a rede de saúde pode não estar captando ou notificando adequadamente os casos existentes.
Ranking com maior volume de Notificações
# usando mapa_final
ranking_mun <- mapa_final |>
sf::st_drop_geometry() |> # remove o desenho do mapa para virar uma tabela leve
filter(Total_Casos > 0) |>
arrange(desc(Total_Casos)) |> # ordenação
slice(1:15) # top 15
# grafico
ggplot(ranking_mun, aes(x = reorder(name_muni, Total_Casos), y = Total_Casos)) +
geom_col(fill = "#C0392B", width = 0.7) +
# nuemero total das notif na ponta da barra
geom_text(aes(label = Total_Casos), hjust = -0.1, size = 3.5, fontface = "bold") +
coord_flip() +
labs(title = "Os 15 municípios com maior Volume de Violência (Notificações)",
x = "",
y = "Número de Notificações") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
axis.text.y = element_text(face = "bold", size = 10)
) +
ylim(0, max(ranking_mun$Total_Casos) * 1.15)A análise da violência não pode ser dissociada dos marcadores sociais. Nesta seção, investigamos a distribuição das notificações segundo a raça/cor autodeclarada, garantindo a visibilidade de todos os grupos étnico-raciais presentes no estado.
Distribuição Racial Completa
O gráfico abaixo compara o volume de notificações entre os grupos raciais. Destacamos a população negra (soma de pretos e pardos), mas também observamos a incidência nas populações branca, amarela e indígena.
dados_raca_analise <- dados_finais |>
mutate(
# padronização
CS_RACA_STR = str_trim(as.character(CS_RACA)),
RACA_COR = case_when(
CS_RACA_STR %in% c("1", "01") ~ "Branca",
CS_RACA_STR %in% c("2", "02") ~ "Preta",
CS_RACA_STR %in% c("3", "03") ~ "Amarela",
CS_RACA_STR %in% c("4", "04") ~ "Parda",
CS_RACA_STR %in% c("5", "05") ~ "Indígena",
str_detect(tolower(CS_RACA_STR), "branca") ~ "Branca",
str_detect(tolower(CS_RACA_STR), "parda") ~ "Parda",
str_detect(tolower(CS_RACA_STR), "preta") ~ "Preta",
str_detect(tolower(CS_RACA_STR), "amarela") ~ "Amarela",
str_detect(tolower(CS_RACA_STR), "indigena|indígena") ~ "Indígena",
TRUE ~ "Ignorado"
),
CATEGORIA_RACA = case_when(
RACA_COR %in% c("Preta", "Parda") ~ "Negra (Preta + Parda)",
RACA_COR == "Branca" ~ "Branca",
RACA_COR == "Amarela" ~ "Amarela",
RACA_COR == "Indígena" ~ "Indígena",
TRUE ~ "Ignorado"
)
) |>
filter(CATEGORIA_RACA != "Ignorado") # remove ignorados
# grafico
ggplot(dados_raca_analise, aes(x = fct_infreq(CATEGORIA_RACA), fill = CATEGORIA_RACA)) +
geom_bar(width = 0.7) +
geom_text(aes(label = ..count..), stat = "count", vjust = -0.5, fontface = "bold") +
scale_fill_manual(values = c(
"Negra (Preta + Parda)" = "#8da0cb",
"Branca" = "#fc8d62",
"Amarela" = "#ffd92f",
"Indígena" = "#66c2a5"
)) +
labs(title = "Perfil Racial das Vítimas de Violência",
subtitle = "Notificações segundo autodeclaração de raça/cor",
x = "",
y = "Número de Casos",
fill = "Grupo Racial") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
legend.position = "none"
)Os dados analisados expõem a centralidade da raça na dinâmica da violência em Pernambuco. A população negra (preta e parda) não apenas representa a maioria absoluta das notificações, refletindo a demografia do estado, mas também apresenta padrões específicos de vitimização
Tipologia por raça: A natureza da violência muda conforme a cor da pele?
dados_raca_tipos <- dados_raca_analise |>
select(CATEGORIA_RACA, starts_with("VIOL_"), -VIOL_MOTIV) |>
pivot_longer(cols = starts_with("VIOL_"), names_to = "TIPO", values_to = "RESPOSTA") |>
filter(RESPOSTA %in% c("Sim", "1")) |>
mutate(
TIPO = str_remove(TIPO, "VIOL_"),
TIPO = case_when(
TIPO == "FISIC" ~ "Física",
TIPO == "PSICO" ~ "Psicológica",
TIPO == "SEXU" ~ "Sexual",
TIPO == "NEGLI" ~ "Negligência",
TRUE ~ NA_character_
)
) |>
filter(!is.na(TIPO))
# grafico
ggplot(dados_raca_tipos, aes(x = TIPO, group = CATEGORIA_RACA, fill = CATEGORIA_RACA)) +
geom_bar(aes(y = after_stat(prop)), position = "dodge", width = 0.7) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("Negra (Preta + Parda)" = "#8da0cb", "Branca" = "#fc8d62",
"Amarela" = "#ffd92f", "Indígena" = "#66c2a5")) +
labs(title = "Natureza da Violência: Comparativo Racial",
subtitle = "Como cada tipo de violência afeta proporcionalmente cada grupo",
x = "", y = "Proporção (%)", fill = "Grupo Racial") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
legend.position = "top",
axis.text = element_text(size = 11)
) Ao comparar a natureza da violência, observa-se que a violência física e a negligência afetam desproporcionalmente a população negra (barra azul). Este dado sugere uma correlação com a vulnerabilidade social, onde a agressão direta e o desamparo são as formas mais prevalentes de violação de direitos.
Por outro lado, a violência psicológica apresenta uma proporção ligeiramente maior entre a população branca (barra laranja) comparada aos outros tipos. Isso pode indicar não uma ausência desse sofrimento na população negra, mas sim uma desigualdade no acesso ao diagnóstico: vítimas brancas podem ter maior facilidade em ter suas queixas de sofrimento mental reconhecidas e notificadas pelo sistema de saúde, enquanto para a população negra, muitas vezes, apenas a violência física visível é registrada.