Acidentes de Trânsito em Recife 2024

Introdução

O trânsito de Recife é um tema bastante relevante para sua população. Portanto, é interessante analisar dados sobre os acidentes de trânsito. Por exemplo, em 2023, 144 pessoas morreram em sinistros de trânsito no Recife. Sendo assim, serão analisados os dados de 2024, investigando se houve mais óbitos comparados ao ano anterior, quais bairros e quais meses tiveram mais acidentes, porcentagem de quantos acidentes tiveram vítimas fatais.

Como visto, diversos dados relevantes para a população recifense podem ser extraídos utilizando os dados disponíveis no portal oficial da cidade, sendo fundamental para identificar padrões e fatores de risco. Entender as circunstâncias que levam a esses acidentes permite o desenvolvimento de políticas públicas direcionadas e campanhas educativas mais eficazes.

Dados

Como foi antecipado, os dados a serem utilizados vão ser obtidos pelo portal oficial de Recife, que são sobre Acidentes de Trânsito em 2024. A partir dessas informações, vão ser extraídos alguns dados, como: quantidade de mortes envolvendo acidentes de trânsito em 2024, meses e bairros com mais acidentes.

Pacotes requeridos

library(rmarkdown) #Utilizado na conversão de arquivo em R em diversos formatos

library(knitr) #Para geração de tabelas

library(dplyr)  #Para manipulação avançada dos DataFrames
## 
## Anexando pacote: 'dplyr'
## Os seguintes objetos são mascarados por 'package:stats':
## 
##     filter, lag
## Os seguintes objetos são mascarados por 'package:base':
## 
##     intersect, setdiff, setequal, union
library(DT) #Para criar tabelas funcionais no HTML

library(lubridate) #Para manipulação avançada de datas
## 
## Anexando pacote: 'lubridate'
## Os seguintes objetos são mascarados por 'package:base':
## 
##     date, intersect, setdiff, union
library(ggplot2) # Para visualização de gráficos

Preparação dos dados

Os dados utilizados foram obtidos no portal oficial de Recife e podem ser acessados através desse link sobre Acidentes de Trânsito em 2024.

Sobre os dados

Estes dados têm como principal propósito mostrar os sinistros de trânsito com e sem vítimas do ano 2024, descrevendo o dia, data, hora e onde aconteceu. Esse conjunto de dados foi criado no dia 29/Julho/2024 e atualizado pela última vez no dia 20/Janeiro/2025, mas todas as suas informações foram coletadas ao decorrer do ano de 2024, apenas agrupadas posteriormente. Originalmente, possui 28 variáveis e 5315 inserções. As colunas são separadas por “;” e na existência de alguma célula vazia, nada é inserido, ficando vazio. A data é inserida no formato AAAA-MM-DD, a hora no formato HH-MM-SS, mas os segundos são sempre 00, ou seja, não são registrados. Ainda sobre a hora, é importante ressaltar que ela está no formato de 12, mas não tem indicação se é AM ou PM, resultando na impossibilidade de saber o período em que aconteceu. Os dados numéricos são inseridos com a sua parte fracionada, por exemplo, “1,0”, mas nunca há decimais, pois os dados são todos inteiros.

Importação

Para realizar a importação dos dados, primeiro eu defino o diretório de trabalho:

setwd("~/CPAD")

E depois faço a importação:

acidentes <- read.csv("acidentes2024.csv", sep=";")
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Sobre o comando acima, vale a pena salientar o uso do sep=“;”, como explicado, as colunas estão separadas por “;” e o comando read.csv espera que elas fossem separadas por “,”, desse modo, tenho que explicitar o símbolo de separação para o comando funcionar corretamente.

Limpeza de dados

Nota-se que a partir da coluna “acidente_verificado” não há dados inseridos. Portanto, irei excluir essas colunas já que não possuem dados. Para isso, vou primeiro descobrir qual é o índice dessa coluna utilizando o seguinte comando:

indice <- which(names(acidentes) == "acidente_verificado")
print(indice)
## [1] 26

E em seguida, excluo todas as colunas desnecessárias, mantendo apenas o que vem antes dela:

acidentes <- acidentes[, 1:(indice-1)]
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Portanto, após esses comandos, restaram 25 colunas e 13 foram excluídas.Mas não são apenas essas colunas que não servem para análise de dados. As colunas “Protocolo”, “endereco”, “numero”, “detalhe_endereco_acidente”, “complemento”, “bairro_cruzamento” e “num_semaforo” também serão removidas. “Protocolo” porque não interessa o id, “bairro_cruzamento” pois os dados contidos nelas são iguais aos dados da coluna “bairro” e as outras listadas pois não precisamos desse nível de detalhes do endereço.

acidentes <- acidentes %>% select(-c(Protocolo, endereco, numero, detalhe_endereco_acidente, complemento, bairro_cruzamento, num_semaforo))
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Após essas novas remoções, sobraram 18 colunas, já que 7 foram excluídas. Agora é preciso remover as linhas cuja a situação seja duplicada, já que contém informações que outro registro tem e cancelada, já que não tem valor para as métricas.

acidentes <- acidentes %>% filter(!(situacao %in% c("DUPLICIDADE", "CANCELADA")))
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Com essa última operação, foram deletadas 385 linhas, restando 4930. Após isso, a coluna “situacao” não tem mais serventia, por isso será deleteda. A coluna “tipo”, “natureza” e “sentido_via” serão transformadas em fatores. Mas antes, o próximo passo é a substituição de células vazias por NA, para facilitar o trabalho do R na interpretação dos dados e também na transformação de algumas colunas em dados númericos. Uma observação importante a ser feita, é que na biblioteca DT, utilizada para a visualização da tabela, trata valores NA como string vazias, por isso o NA não ta sendo observado.

acidentes <- acidentes %>% mutate_all(~na_if(., ""))
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Mas antes de fazer, como comentado acima, preciso tratar os dados da coluna sentido_via, pois há dados incorretos:

acidentes$sentido_via[acidentes$sentido_via == "1987"] <- NA
acidentes$sentido_via[acidentes$sentido_via %in% c("BOA VIAGEM", "PRAIA", "CI", "CID")] <- "CIDADE"
acidentes$sentido_via[acidentes$sentido_via %in% c("OLINDA", "SUB")] <- "SUBURBIO"

acidentes <- acidentes %>%
  select(-situacao) %>%
  mutate(across(c(tipo, natureza, sentido_via), as.factor))
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Verificando os níveis de cada um dos fatores:

levels(acidentes$tipo) 
##  [1] "ATROPELAMENTO DE ANIMAL" "ATROPELAMENTO DE PESSOA"
##  [3] "CAPOTAMENTO"             "CHOQUE"                 
##  [5] "COLISÃO"                 "COLISÃO COM CICLISTA"   
##  [7] "COLISÃO FRONTAL"         "COLISÃO LATERAL"        
##  [9] "COLISÃO TRANSVERSAL"     "COLISÃO TRASEIRA"       
## [11] "ENGAVETAMENTO"           "QUEDA"                  
## [13] "TOMBAMENTO"
levels(acidentes$natureza)
## [1] "COM VÍTIMA"   "SEM VÍTIMA"   "VÍTIMA FATAL"
levels(acidentes$sentido_via) 
## [1] "CIDADE"   "SUBURBIO"

Dados finais

Passado todas essas manipulações, aqui esta resumidamente em algumas linhas como ficou o conjunto de dados final:

datatable(head(acidentes, 10), options = list(scrollX = TRUE))

4930 linhas e 17 colunas, sendo que dessas 17 colunas, 3 são fatores. Sobre as variáveis, temos:

  1. data: se refere ao dia em que ocorreu o sinistro
  2. hora: se refere a hora em que ocorreu o sinistro
  3. natureza: se o sinistro houve vítima ou não
  4. bairro: onde ocorreu o sinistro
  5. sentido_via: o sentido em que o envolvido se deslocava antes do sinistro
  6. tipo: o tipo do sinistro (colisão, atropelamento…)
  7. auto: quantos carros estavam envolvidos no sinistro
  8. moto: quantas motos estavam envolvidas no sinistro
  9. ciclom: quantos ciclomotores (veículo de duas ou três rodas, provido de um motor de combustão interna ou elétrico, cuja cilindrada não exceda 50 cm³ ou 4 kW e cuja velocidade máxima de fabricação não exceda a 50 km/h) estavam envolvidos no sinistro
  10. ciclista: quantos ciclistas estavam envolvidos no sinistro
  11. pedestre: quantos pedestres estavam envolvidos no sinistro
  12. onibus: quantos ônibus estavam envolvidos no sinistro
  13. caminhao: quantos caminhões estavam envolvidos no sinistro
  14. viatura: quantas viaturas estavam envolvidas no sinistro
  15. outros: quantos meios de locomoção não listados(pode ser skate, por exemplo) estavam envolvidos no sinistro
  16. vitimas: quantas vítimas estavam envolvidas no sinistro
  17. vitimasfatais: quantas vítimas faleceram no sinistro

Análise exploratória dos dados

Primeiro, vou criar uma nova variável chamada região, onde nela vai conter a região em que ocorreu o acidente. Recife tem 6 regiões:

  1. Região central: Bairro do Recife; Santo Amaro ; Boa Vista; Cabanga; Ilha do Leite; Paissandu; Santo Antônio: São José; Coelhos; Soledade; Ilha Joana Bezerra.
  2. Região norte: Arruda; Campina do Barreto; Encruzilhada; Hipódromo; Peixinhos; Ponto de Parada; Rosarinho; Torreão; Água Fria; Alto Santa Terezinha; Bomba do Hemetério; Cajueiro; Fundão; Porto da Madeira; Beberibe; Dois Unidos; Linha do Tiro.
  3. Região noroeste: Aflitos; Alto do Mandu; Alto José Bonifácio; Alto José do Pinho; Apipucos; Brejo da Guabiraba; Brejo de Beberibe; Casa Amarela; Casa Forte; Córrego do Jenipapo; Derby; Dois Irmãos; Espinheiro; Graças; Guabiraba; Jaqueira; Macaxeira; Monteiro; Nova Descoberta; Parnamirim; Passarinho; Pau-Ferro; Poço da Panela, Santana; Sítio dos Pintos; Tamarineira; Mangabeira; Morro da Conceição; Vasco da Gama.
  4. Região oeste: Cordeiro; Ilha do Retiro; Iputinga; Madalena; Prado; Torre; Zumbi; Engenho do Meio; Torrões; Caxangá; Cidade Universitária; Várzea.
  5. Região sul: Afogados; Areias; Barro; Bongi; Caçote; Coqueiral; Curado; Estância; Jardim São Paulo; Jiquiá; Mangueria; Mustardinha; San Martin; Sancho; Tejipió; Totó.
  6. Região sudoeste: Boa Viagem; Brasília Teimosa; Imbiribeira; Ipsep; Pina; Ibura; Jordão; Cohab.
acidentes <- acidentes %>%
  mutate(regiao = case_when(
    bairro %in% c("BAIRRO DO RECIFE", "SANTO AMARO", "BOA VISTA", "CABANGA", "ILHA DO LEITE", "PAISSANDU", "SANTO ANTONIO", "SAO JOSE", "COELHOS", "SOLEDADE", "ILHA JOANA BEZERRA", "JOANA BEZERRA" ) ~ "central",
    bairro %in% c("ARRUDA", "CAMPINA DO BARRETO", "ENCRUZILHADA", "HIPODROMO", "CAMPO GRANDE", "PEIXINHOS", "PONTO DE PARADA", "ROSARINHO", "TORREAO", "AGUA FRIA", "ALTO SANTA TERESINHA", "BOMBA DO HEMETERIO", "CAJUEIRO", "FUNDAO", "PORTO DA MADEIRA", "BEBERIBE", "DOIS UNIDOS", "LINHA DO TIRO") ~ "norte",
    bairro %in% c("AFLITOS", "ALTO DO MANDU", "ALTO JOSE BONIFACIO", "ALTO JOSE DO PINHO", "APIPUCOS", "BREJO DA GUABIRABA", "BREJO DE BEBERIBE", "CASA AMARELA", "CASA FORTE", "CORREGO DO JENIPAPO", "DERBY", "DOIS IRMAOS", "ESPINHEIRO", "GRACAS", "GUABIRABA", "JAQUEIRA", "MACAXEIRA", "MONTEIRO", "NOVA DESCOBERTA", "PARNAMIRIM", "PASSARINHO", "PAU-FERRO", "POCO DA PANELA", "SANTANA", "SITIO DOS PINTOS", "TAMARINEIRA", "MANGABEIRA", "MORRO DA CONCEICAO", "VASCO DA GAMA") ~ "noroeste",
    bairro %in% c("CORDEIRO", "ILHA DO RETIRO", "IPUTINGA", "MADALENA", "PRADO", "TORRE", "ZUMBI", "ENGENHO DO MEIO", "TORROES", "CAXANGA", "CIDADE UNIVERSITARIA", "VARZEA") ~ "oeste",
    bairro %in% c("AFOGADOS", "AREIAS", "BARRO", "BONGI", "CACOTE", "COQUEIRAL", "CURADO", "ESTANCIA", "JARDIM SAO PAULO", "JIQUIA", "MANGUEIRA", "MUSTARDINHA", "SAN MARTIN", "SANCHO", "TEJIPIO", "TOTO") ~ "sul",
    bairro %in% c("BOA VIAGEM", "BRASILIA TEIMOSA", "IMBIRIBEIRA", "IPSEP", "PINA", "IBURA", "JORDAO", "COHAB") ~ "sudoeste",
    TRUE ~ "Desconhecida"  #Caso o bairro não esteja na lista
  ))
datatable(head(acidentes, 5), options = list(scrollX = TRUE))

Vou também criar uma tabela em que me mostra quantos acidentes teve por mês, juntamente com seu gráfico:

meses <- c("jan", "fev", "mar", "abr", "mai", "jun", 
               "jul", "ago", "set", "out", "nov", "dez")

# Criar o novo dataframe com a contagem de acidentes por mês
acidentes_mes <- acidentes %>%
  mutate(
    mes = factor(format(as.Date(data), "%b"), 
                 levels = format(seq(as.Date("2024-01-01"), by = "month", length.out = 12), "%b"),
                 labels = meses)
  ) %>%
  group_by(mes) %>%
  summarise(quantidade = n(), .groups = "drop")

print(acidentes_mes)
## # A tibble: 12 × 2
##    mes   quantidade
##    <fct>      <int>
##  1 jan          365
##  2 fev          323
##  3 mar          385
##  4 abr          389
##  5 mai          408
##  6 jun          407
##  7 jul          438
##  8 ago          451
##  9 set          473
## 10 out          416
## 11 nov          432
## 12 dez          443
ggplot(acidentes_mes, aes(x = mes, y = quantidade, fill = mes)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  labs(title = "Número de Acidentes por Mês", 
       x = "Mês", 
       y = "Quantidade de Acidentes") +
  theme_minimal() +
  theme(text = element_text(size = 14))

E outra tabela e gráfico que mostra os acidentes por regiões como também a porcentagem:

acidentes_regiao <- acidentes %>%
  group_by(regiao) %>%
  summarise(quantidade = n(), .groups = "drop") %>%
  arrange(desc(quantidade)) # Ordena da maior para a menor quantidade

acidentes_regiao <- acidentes_regiao %>%
  mutate(perc = quantidade / sum(quantidade) * 100,  # Calcula percentual
         label = paste0(regiao, "\n", quantidade, " (", round(perc, 1), "%)")) # Rótulo com nome, valor e percentual

# Exibir o novo dataframe
print(acidentes_regiao)
## # A tibble: 7 × 4
##   regiao       quantidade   perc label                   
##   <chr>             <int>  <dbl> <chr>                   
## 1 sudoeste           1285 26.1   "sudoeste\n1285 (26.1%)"
## 2 oeste               827 16.8   "oeste\n827 (16.8%)"    
## 3 central             815 16.5   "central\n815 (16.5%)"  
## 4 noroeste            809 16.4   "noroeste\n809 (16.4%)" 
## 5 sul                 629 12.8   "sul\n629 (12.8%)"      
## 6 norte               559 11.3   "norte\n559 (11.3%)"    
## 7 Desconhecida          6  0.122 "Desconhecida\n6 (0.1%)"
## Criar o gráfico de pizza com valores
ggplot(acidentes_regiao, aes(x = "", y = quantidade, fill = regiao)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar(theta = "y") + 
  geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 3.2) + #Adiciona os valores dentro das fatias
  labs(title = "Distribuição de Acidentes por Região") +
  theme_minimal() +
  theme(axis.text.x = element_blank(), 
        axis.ticks = element_blank(), 
        panel.grid = element_blank()) +
  guides(fill = guide_legend(title = "Região"))

Com isso, descobrimos que a maioria dos acidentes do ano de 2024 foram na região sudoeste, como também o mês que ocorreu mais sinistros, sendo este o mês de Setembro.

Podemos verificar, também qual ocorrência é a mais comum:

## Criar um dataframe agrupando por tipo de colisão
acidentes_tipo <- acidentes %>%
  group_by(tipo) %>%
  summarise(quantidade = n(), .groups = "drop") %>%
  arrange(desc(quantidade)) # Ordena da maior para a menor quantidade

# Exibir o novo dataframe
print(acidentes_tipo)
## # A tibble: 14 × 2
##    tipo                    quantidade
##    <fct>                        <int>
##  1 COLISÃO                       2576
##  2 COLISÃO LATERAL               1176
##  3 COLISÃO TRASEIRA               359
##  4 COLISÃO FRONTAL                250
##  5 ATROPELAMENTO DE PESSOA        170
##  6 CHOQUE                         113
##  7 COLISÃO COM CICLISTA            84
##  8 QUEDA                           74
##  9 COLISÃO TRANSVERSAL             61
## 10 <NA>                            26
## 11 CAPOTAMENTO                     20
## 12 ENGAVETAMENTO                   11
## 13 TOMBAMENTO                       7
## 14 ATROPELAMENTO DE ANIMAL          3
##Criar o gráfico de barras
ggplot(acidentes_tipo, aes(x = reorder(tipo, -quantidade), y = quantidade, fill = tipo)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  labs(title = "Número de Acidentes por Tipo de Colisão", 
       x = "Tipo de Colisão", 
       y = "Quantidade de Acidentes") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 12))

Logo, o tipo mais comum é colisão, sem explicitar o tipo de colisão, seguido de colisão lateral.

Por fim, outro dado importante é sobre o quantitativo de acidentes com vítimas e vítimas fatais.

## Contar o total de acidentes
acidentes_total <- nrow(acidentes)

## Agrupar por natureza e calcular a quantidade e porcentagem
acidentes_natureza <- acidentes %>%
  group_by(natureza) %>%
  summarise(quantidade = n(), .groups = "drop") %>%
  mutate(porcentagem = (quantidade / acidentes_total) * 100) %>%
  arrange(desc(quantidade))  # Ordena do maior para o menor

# Exibir o resultado
print(acidentes_natureza)
## # A tibble: 3 × 3
##   natureza     quantidade porcentagem
##   <fct>             <int>       <dbl>
## 1 COM VÍTIMA         4339      88.0  
## 2 SEM VÍTIMA          558      11.3  
## 3 VÍTIMA FATAL         33       0.669
##Criar o gráfico de barras horizontais
ggplot(acidentes_natureza, aes(x = reorder(natureza, porcentagem), y = porcentagem, fill = natureza)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = paste0(quantidade, " (", round(porcentagem, 1), "%)")), 
            hjust = -0.2, size = 5) +  # Exibe "Quantidade (Porcentagem%)"
  labs(title = "Distribuição de Acidentes por Natureza", 
       x = "Natureza do Acidente", 
       y = "Porcentagem (%)") +
  theme_minimal() +
  coord_flip() + # Deixa as barras horizontais
  expand_limits(y = max(acidentes_natureza$porcentagem) * 1.5)  # Adiciona mais espaço no eixo Y

Isso nós mostrou que apenas 0,7%, ou seja, 33 de 4930 tiveram vítimas fatais.

Conclusão

Este trabalho teve como propósito analisar os acidentes de trânsito ocorridos em Recife no ano de 2024. Com isso, foi possível obter informações pertinentes e que ajudam toda a sociedade recifense.

Portanto, os meios utilizados para chegar nos resultados adequados foram, primeiramente, realizar uma limpa nos dados desnecessários e corrigir dados que estavam errados, como também a criação de novos dados a partir dos existentes no portal oficial da cidade de Recife.

Após todas as manipulações, descobrimos dados interessantes. Por exemplo, o mês em que mais aconteceram sinistros foi em setembro. A região que mais ocorreu acidentes foi a sudoeste, que compreende os seguintes bairros: Boa Viagem; Brasília Teimosa; Imbiribeira; Ipsep; Pina; Ibura; Jordão; Cohab. O tipo de colisão mais frequente não é tão explicito nos dados, pois geralmente, a maioria tem somente “colisão”, mas logo em seguida, temos a “colisão lateral” como a mais comum. Por último, felizmente, apenas 0,7% dos acidentes houve fatalidades. Representando uma redução de 66.67% comparada com as fatalidades em acidentes em 2023, já que houve 48 óbitos.

Estes possibilitam a população saber as localidades em que o risco de acidente é maior, como também as repartições públicas, já que conseguem intensificar campanhas de trânsitos em regiões com maior índice de acidentes, além de saber se campanhas anteriores surtiram efeito com base na redução de óbitos comparado ao ano de 2023.

Como limitações, não foi possível saber o período do dia em que acidentes são mais comuns e mais fatais. Isso seria possessível se os dados sobre a hora estivessem no formato 24h ou com AM, ou PM. Além disso, poderia detalhar mais sobre os dados relacionados ao tipo de automóvel envolvido no sinistro, a fim de, por exemplo, oferecer mais possibilidade de campanhas publicitárias direcionadas aos motoristas específicos para cada automóvel.