Introdução

O trânsito representa um dos principais desafios para a segurança pública e a mobilidade urbana. Acidentes viários resultam não apenas em perdas humanas, mas também em impactos sociais e econômicos significativos. Com base nos dados fornecidos pela Polícia Rodoviária Federal e diponibilizado no Kaggle no link: Car Accidents in Brazil (2017-2023), este estudo analisa acidentes de trânsito ocorridos no Brasil entre os anos de 2017 e 2023, buscando identificar padrões e fatores determinantes que influenciam a ocorrência e gravidade dos incidentes.

O objetivo principal deste trabalho é investigar os fatores que mais contribuem para os acidentes, incluindo falha humana, condições climáticas e estado das vias. Além disso, pretende-se explorar a distribuição temporal e espacial dos acidentes, bem como avaliar a severidade dos impactos em termos de feridos e fatalidades.

Pacotes Necessários

Os seguintes pacotes são utilizados neste projeto:
Pacote Descrição
tidyverse Conjunto de pacotes para manipulação e visualização de dados
lubridate Pacote utilizado na manipulação de datas e horas
knitr Utilizado para formatação e geração de relatórios
DT Permite criar tabelas interativas
ggplot2 Visualização de dados com gráficos estatísticos
sf Análise espacial e manipulação de dados geográficos
ggmap Criação de mapas interativos e estáticos
rnaturalearth Obtenção de shapefiles geográficos
rnaturalearthdata Dados geográficos para análise
Precisamos nos certificar de que os mesmos estão instalados:
install.packages(c("tidyverse", "lubridate", "knitr", "DT", "ggplot2", "sf", "ggmap"))
Em seguida, carregamos os pacotes no ambiente:
library(tidyverse)
library(lubridate)
library(knitr)
library(DT)
library(ggplot2)
library(sf)
library(ggmap)
library(rnaturalearth)
library(rnaturalearthdata)

Preparação dos Dados

Fonte e Descrição dos Dados

Os dados utilizados neste estudo foram disponibilizados pela Polícia Rodoviária Federal e podem ser acessados no Kaggle: Car Accidents in Brazil (2017-2023). O conjunto de dados contém 463.152 registros e 27 variáveis, abrangendo informações detalhadas sobre acidentes em rodovias federais no Brasil entre 2017 e 2023.

O propósito original dos dados é fornecer estatísticas sobre acidentes para análises de segurança viária, planejamento de políticas públicas e melhorias na infraestrutura rodoviária. As principais variáveis incluem:

  • Data e hora do acidente (data_inversa, horario)
  • Localização geográfica (uf, br, km, municipio, latitude, longitude)
  • Causa do acidente (causa_acidente)
  • Classificação do acidente (classificacao_acidente)
  • Condições climáticas (condicao_metereologica)
  • Número de vítimas (mortos, feridos_leves, feridos_graves, ilesos)

Os valores ausentes ocorrem principalmente em variáveis como BR e quilômetro do acidente, que podem não ter sido registrados corretamente no momento da coleta dos dados.

Carregamento dos Dados

archive <- "accidents_2017_to_2023_portugues.csv"
df <- read.csv(archive, stringsAsFactors = FALSE)

datatable(head(df, 5), options = list(scrollX = TRUE, searching = FALSE, lengthChange = FALSE))
glimpse(df)
## Rows: 463,152
## Columns: 27
## $ data_inversa           <chr> "2017-01-01", "2017-01-01", "2017-01-01", "2017…
## $ dia_semana             <chr> "domingo", "domingo", "domingo", "domingo", "do…
## $ horario                <chr> "01:45:00", "01:00:00", "04:40:00", "06:30:00",…
## $ uf                     <chr> "RS", "PR", "BA", "PA", "GO", "RN", "PR", "MG",…
## $ br                     <int> 116, 376, 101, 316, 20, 405, 376, 262, 364, 316…
## $ km                     <chr> "34,9", "636", "65", "72,5", "220,5", "30", "24…
## $ municipio              <chr> "VACARIA", "TIJUCAS DO SUL", "ENTRE RIOS", "CAS…
## $ causa_acidente         <chr> "Defeito Mecânico no Veículo", "Velocidade Inco…
## $ tipo_acidente          <chr> "Colisão traseira", "Saída de leito carroçável"…
## $ classificacao_acidente <chr> "Com Vítimas Feridas", "Com Vítimas Fatais", "C…
## $ fase_dia               <chr> "Plena Noite", "Plena Noite", "Amanhecer", "Ama…
## $ sentido_via            <chr> "Decrescente", "Crescente", "Decrescente", "Dec…
## $ condicao_metereologica <chr> "Céu Claro", "Garoa/Chuvisco", "Nublado", "Céu …
## $ tipo_pista             <chr> "Simples", "Dupla", "Simples", "Simples", "Simp…
## $ tracado_via            <chr> "Reta", "Curva", "Curva", "Reta", "Desvio Tempo…
## $ pessoas                <int> 6, 2, 5, 4, 3, 2, 5, 2, 3, 2, 7, 4, 2, 1, 2, 3,…
## $ mortos                 <int> 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 2, 0, 0, 1, 0,…
## $ feridos_leves          <int> 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 2, 0, 1, 1, 0, 0,…
## $ feridos_graves         <int> 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,…
## $ ilesos                 <int> 2, 1, 2, 3, 0, 1, 4, 2, 0, 1, 2, 1, 1, 0, 1, 1,…
## $ ignorados              <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,…
## $ feridos                <int> 4, 0, 2, 0, 3, 0, 1, 0, 3, 0, 3, 0, 1, 1, 0, 1,…
## $ veiculos               <int> 2, 2, 2, 3, 1, 2, 2, 2, 1, 2, 4, 2, 2, 1, 2, 1,…
## $ latitude               <dbl> -28.507120, -25.754000, -11.961800, -1.289980, …
## $ longitude              <dbl> -50.94118, -49.12660, -38.09530, -47.83483, -46…
## $ regional               <chr> "SPRF-RS", "SPRF-PR", "SPRF-BA", "SPRF-PA", "SP…
## $ delegacia              <chr> "DEL05-RS", "DEL01-PR", "DEL01-BA", "DEL01-PA",…

Limpeza e Preparação

O processo de limpeza inclui:
  • Conversão de datas: A variável data_inversa é convertida para o formato adequado.
  • Correção de valores numéricos: km contém separadores decimais inconsistentes e precisa ser ajustado.
  • Padronização de colunas categóricas: br deve ser tratada como caractere.
  • Remoção de colunas irrelevantes para a análise: As colunas sentido_via, regional e delegacia foram removidas, pois não serão utilizadas nos objetivos deste estudo.
df <- df %>%
  mutate(
    data_inversa = as.Date(data_inversa, format = "%Y-%m-%d"),
    km = as.numeric(gsub(",", ".", km)),
    br = as.character(br)
  ) %>%
  select(-c(sentido_via, regional, delegacia))

df %>% summarise(across(everything(), ~ sum(is.na(.))))
##   data_inversa dia_semana horario uf  br  km municipio causa_acidente
## 1            0          0       0  0 990 990         0              0
##   tipo_acidente classificacao_acidente fase_dia condicao_metereologica
## 1             0                      0        0                      0
##   tipo_pista tracado_via pessoas mortos feridos_leves feridos_graves ilesos
## 1          0           0       0      0             0              0      0
##   ignorados feridos veiculos latitude longitude
## 1         0       0        0        0         0
Após as modificações notamos que há valores faltantes nas colunas km e br, precisamos remover estes registros.
df <- df %>% drop_na(br, km)
df %>% summarise(across(everything(), ~ sum(is.na(.))))
##   data_inversa dia_semana horario uf br km municipio causa_acidente
## 1            0          0       0  0  0  0         0              0
##   tipo_acidente classificacao_acidente fase_dia condicao_metereologica
## 1             0                      0        0                      0
##   tipo_pista tracado_via pessoas mortos feridos_leves feridos_graves ilesos
## 1          0           0       0      0             0              0      0
##   ignorados feridos veiculos latitude longitude
## 1         0       0        0        0         0
Após a limpeza, os dados finais têm a seguinte estrutura:
datatable(head(df, 10), options = list(scrollX = TRUE, searching = FALSE, lengthChange = FALSE))
glimpse(df)
## Rows: 462,162
## Columns: 24
## $ data_inversa           <date> 2017-01-01, 2017-01-01, 2017-01-01, 2017-01-01…
## $ dia_semana             <chr> "domingo", "domingo", "domingo", "domingo", "do…
## $ horario                <chr> "01:45:00", "01:00:00", "04:40:00", "06:30:00",…
## $ uf                     <chr> "RS", "PR", "BA", "PA", "GO", "RN", "PR", "MG",…
## $ br                     <chr> "116", "376", "101", "316", "20", "405", "376",…
## $ km                     <dbl> 34.9, 636.0, 65.0, 72.5, 220.5, 30.0, 249.5, 48…
## $ municipio              <chr> "VACARIA", "TIJUCAS DO SUL", "ENTRE RIOS", "CAS…
## $ causa_acidente         <chr> "Defeito Mecânico no Veículo", "Velocidade Inco…
## $ tipo_acidente          <chr> "Colisão traseira", "Saída de leito carroçável"…
## $ classificacao_acidente <chr> "Com Vítimas Feridas", "Com Vítimas Fatais", "C…
## $ fase_dia               <chr> "Plena Noite", "Plena Noite", "Amanhecer", "Ama…
## $ condicao_metereologica <chr> "Céu Claro", "Garoa/Chuvisco", "Nublado", "Céu …
## $ tipo_pista             <chr> "Simples", "Dupla", "Simples", "Simples", "Simp…
## $ tracado_via            <chr> "Reta", "Curva", "Curva", "Reta", "Desvio Tempo…
## $ pessoas                <int> 6, 2, 5, 4, 3, 2, 5, 2, 3, 2, 7, 4, 2, 1, 2, 3,…
## $ mortos                 <int> 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 2, 0, 0, 1, 0,…
## $ feridos_leves          <int> 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 2, 0, 1, 1, 0, 0,…
## $ feridos_graves         <int> 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,…
## $ ilesos                 <int> 2, 1, 2, 3, 0, 1, 4, 2, 0, 1, 2, 1, 1, 0, 1, 1,…
## $ ignorados              <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,…
## $ feridos                <int> 4, 0, 2, 0, 3, 0, 1, 0, 3, 0, 3, 0, 1, 1, 0, 1,…
## $ veiculos               <int> 2, 2, 2, 3, 1, 2, 2, 2, 1, 2, 4, 2, 2, 1, 2, 1,…
## $ latitude               <dbl> -28.507120, -25.754000, -11.961800, -1.289980, …
## $ longitude              <dbl> -50.94118, -49.12660, -38.09530, -47.83483, -46…

Análise Exploratória

Distribuição Temporal dos Acidentes

df %>% 
  mutate(year = lubridate::year(data_inversa)) %>%
  count(year) %>%
  ggplot(aes(x = year, y = n)) +
  geom_line() +
  labs(title = "Número de Acidentes por Ano", x = "Ano", y = "Número de Acidentes")

df %>% 
  mutate(year = lubridate::year(data_inversa), month = lubridate::month(data_inversa, label = TRUE)) %>%
  count(year, month) %>%
  ggplot(aes(x = month, y = n, group = year, color = as.factor(year))) +
  geom_line() +
  geom_point() +
  labs(title = "Distribuição Mensal dos Acidentes por Ano", x = "Mês", y = "Número de Acidentes", color = "Ano") +
  theme_minimal()

Embora haja uma tendência de queda e estabilidade na distribuição anual, fica notório que em todos os anos há um aumento no número de acidentes no mês de dezembro. O que pode ser explicado por inúmeros fatores, como o maior fluxo nas rodovias durante o mês.

Análise Geográfica dos Acidentes

br_states <- ne_states(country = "Brazil", returnclass = "sf")

accidents_by_state <- df %>%
  count(uf) %>%
  rename(abbrev = uf)

br_states <- br_states %>%
  left_join(accidents_by_state, by = c("postal" = "abbrev"))

ggplot(br_states) +
  geom_sf(aes(fill = n), color = "white") +
  scale_fill_viridis_c(option = "plasma", na.value = "grey80") +
  labs(title = "Número de Acidentes por Estado", fill = "Acidentes") +
  theme_minimal()

Embora não seja o estado mais populoso do Brasil, Minas Gerais lidera no número de acidentes. Muito devido ao fato de uma grande e extensa malha rodoviária com alto fluxo de caminhões, que transportam principalmente minério.

df %>%
  count(br, sort = TRUE) %>%
  top_n(10, n) %>%
  ggplot(aes(x = reorder(br, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(
    title = "BRs com Mais Acidentes",
    x = "Rodovia (BR)",
    y = "Número de Acidentes"
  ) +
  theme_minimal()

df %>%
  filter(uf == "MG") %>%
  count(br, sort = TRUE) %>%
  ggplot(aes(x = reorder(br, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(
    title = "Número de Acidentes por BR em Minas Gerais",
    x = "Rodovia (BR)",
    y = "Número de Acidentes"
  ) +
  theme_minimal()

Principais Causas dos Acidentes

df %>%
  count(causa_acidente, sort = TRUE) %>%
  top_n(10) %>%
  ggplot(aes(x = reorder(causa_acidente, n), y = n)) +
  geom_col(fill = "red") +
  coord_flip() +
  labs(title = "Top 10 Causas de Acidentes", x = "Causa", y = "Quantidade")
## Selecting by n

A análise das principais causas de acidentes no Brasil revela que a falta de atenção à condução é o fator mais recorrente, contribuindo significativamente para o número total de ocorrências. Esse comportamento pode estar relacionado a distrações como o uso do celular ao volante, conversas com passageiros, fadiga ou desatenção momentânea.

Impacto das Condições Climáticas

df %>%
  count(condicao_metereologica) %>%
  ggplot(aes(x = reorder(condicao_metereologica, n), y = n)) +
  geom_col(fill = "blue") +
  coord_flip() +
  labs(title = "Distribuição de Acidentes por Condição Climática", x = "Condição Climática", y = "Quantidade")

Conclusão

A análise dos acidentes de trânsito no Brasil entre 2017 e 2023 evidencia que a falha humana é o principal fator contribuinte para a ocorrência dessas tragédias. Entre os fatores mais recorrentes, a falta de atenção à condução se destaca como a maior causa de acidentes, possivelmente associada a distrações como o uso do celular, fadiga e desatenção momentânea. Além disso, a velocidade incompatível com a via e o consumo de álcool continuam sendo fatores críticos que comprometem a segurança viária.

A distribuição temporal dos acidentes revela um pico no mês de dezembro, período em que o fluxo nas rodovias aumenta devido às festividades de fim de ano. No aspecto geográfico, Minas Gerais lidera em número de acidentes, o que pode ser explicado por sua extensa malha rodoviária e pelo alto fluxo de caminhões transportando mercadorias.

As condições climáticas adversas, como chuva e neblina, também exercem influência na ocorrência de acidentes, reforçando a necessidade de investimentos em infraestrutura, sinalização e conscientização dos motoristas para minimizar riscos em condições desfavoráveis.

Diante desses achados, futuras investigações podem focar no desenvolvimento de modelos preditivos para identificar padrões de risco e antecipar cenários de maior vulnerabilidade. Além disso, ações como fiscalização rigorosa, educação no trânsito e melhoria das condições das rodovias são essenciais para reduzir o número de acidentes e tornar as estradas mais seguras para todos.