O excesso de velocidade nas vias urbanas representa um dos principais fatores de risco para acidentes de trânsito graves e fatais. Em Recife, uma metrópole com mais de 1,6 milhão de habitantes e intensa circulação diária de veículos, a análise dos dados de fiscalização eletrônica de velocidade oferece uma oportunidade única para compreender padrões de comportamento dos motoristas e identificar áreas críticas que demandam intervenção.
Este estudo é relevante para diversos públicos:
Segundo a Organização Mundial da Saúde, a cada 1% de aumento na velocidade média, há um aumento de 4% no risco de acidentes fatais. Isso torna o monitoramento e análise desses dados não apenas uma questão administrativa, mas de saúde pública.
Este projeto busca responder às seguintes questões:
Para abordar estas questões, adotei uma metodologia de análise exploratória de dados (EDA) utilizando a linguagem R e um conjunto de pacotes especializados para manipulação e visualização de dados. O processo incluiu:
Uma característica fundamental desta abordagem é a conversão dos dados do formato “largo” para o formato “longo”, permitindo análises mais granulares e a criação de novas variáveis derivadas, como a classificação de infrações e o cálculo de excesso percentual de velocidade.
Os resultados deste estudo podem beneficiar diversos grupos:
Esta análise também contribui para o movimento de dados abertos e ciência de dados aplicada à gestão pública, demonstrando como informações coletadas rotineiramente podem gerar insights valiosos quando adequadamente processadas e interpretadas.
# Manipulação de dados
library(tidyverse) # Conjunto de pacotes para manipulação de dados
library(readr) # Importação eficiente de dados
library(lubridate) # Manipulação de datas
library(janitor) # Limpeza de nomes de variáveis
# Visualização
library(ggplot2) # Criação de gráficos
library(plotly) # Gráficos interativos
library(leaflet) # Mapas interativos
library(viridis) # Paletas de cores acessíveis
library(scales) # Formatação de escalas em gráficos
# Apresentação
library(knitr) # Geração de relatórios dinâmicos
library(kableExtra) # Tabelas formatadas
library(DT) # Tabelas interativas
library(flexdashboard) # Layout de dashboardEsta análise utiliza diversos pacotes R, cada um com funções específicas que se complementam:
Pacotes para manipulação de dados: -
tidyverse: Um meta-pacote que inclui ferramentas
essenciais como dplyr (manipulação), tidyr (organização), purrr
(programação funcional) e ggplot2 (visualização). Utilizo principalmente
as funções de filtragem, agrupamento e sumarização. -
readr: Oferece funções mais rápidas e flexíveis para
importação de dados, especialmente útil para lidar com os diferentes
formatos de arquivos CSV dos equipamentos de fiscalização. -
lubridate: Simplifica a manipulação de datas e horas,
permitindo extrair facilmente componentes como dia da semana e criar
classificações temporais. - janitor: Facilita a limpeza
de nomes de variáveis e dados com funções como
clean_names().
Pacotes para visualização: - ggplot2: Implementa a “gramática dos gráficos” para criar visualizações estatísticas complexas com código declarativo. - plotly: Permite converter gráficos estáticos em interativos, facilitando a exploração dos padrões temporais. - leaflet: Integra a biblioteca JavaScript Leaflet para criar mapas interativos dos pontos de fiscalização. - viridis: Fornece paletas de cores cientificamente validadas e perceptualmente uniformes, importantes para visualizações acessíveis. - scales: Facilita a formatação de números em gráficos, especialmente útil para valores formatados com separadores de milhar.
Pacotes para apresentação: - knitr: Integra código R e resultados em um documento dinâmico. - kableExtra: Estende as funcionalidades de tabulação do knitr, permitindo criar tabelas bem formatadas. - DT: Cria tabelas interativas com recursos de pesquisa, paginação e ordenação. - flexdashboard: Fornece a estrutura para organizar o relatório em formato de dashboard.
Os dados utilizados neste estudo foram obtidos do Portal de Dados Abertos da Prefeitura do Recife, especificamente da seção de “Mobilidade Urbana”. Estes dados são coletados pela Autarquia de Trânsito e Transporte Urbano do Recife (CTTU) como parte do programa de fiscalização eletrônica de velocidade no município.
O conjunto de dados representa registros completos de 2020, cobrindo todo o sistema de monitoramento de velocidade da cidade, que inclui dois tipos principais de equipamentos:
Estes dados são coletados em tempo real pelos equipamentos, que registram o número de veículos que passam por cada faixa de velocidade em intervalos de 15 minutos, 24 horas por dia, 7 dias por semana. O propósito original desta coleta é administrativo e fiscalizatório, visando monitorar o cumprimento dos limites de velocidade e direcionar ações de educação e fiscalização no trânsito.
O conjunto de dados original está dividido em múltiplos arquivos:
lombadas-fotossensores.csv): Contém informações sobre cada
equipamento de fiscalização, incluindo:
recife-fotossensores-20-janeiro.csv): 12 arquivos (um para
cada mês) contendo os registros de velocidade dos fotossensores, com as
variáveis:
janeirolomb2020.csv): 12 arquivos (um para cada mês)
contendo os registros de velocidade das lombadas eletrônicas, com
estrutura similar às tabelas de fotossensores.Uma peculiaridade importante destes dados é que eles estão em formato “largo”, onde cada faixa de velocidade é uma coluna separada, tornando necessária uma transformação para formato “longo” para facilitar as análises.
Outros desafios incluem: - Nomenclatura inconsistente entre arquivos mensais - Diferentes separadores decimais (vírgula em vez de ponto) - Falta de padronização nos identificadores de equipamentos (alguns com sufixo “REC”) - Potenciais dados faltantes ou inconsistentes
O processo de importação foi estruturado para lidar com as particularidades dos arquivos:
# Importando dados dos equipamentos
lombadas_fotossensores <- read_delim("lombadas-fotossensores.csv",
delim = ";",
locale = locale(decimal_mark = ",")) %>%
mutate(
velocidade_via = as.integer(str_extract(velocidade_via, "\\d+")),
equipamento = as.character(equipamento) # Garantir que equipamento é character
)
# Função para importar dados mensais de fotossensores
importar_fotossensores_mensais <- function(mes) {
arquivo <- sprintf("recife-fotossensores-20-%s.csv", mes)
dados <- read_delim(arquivo,
delim = ";",
locale = locale(decimal_mark = ","),
col_types = cols(
mes = col_integer(),
equipamento = col_character(),
faixa = col_integer(),
data = col_date(format = ""),
hora = col_integer(),
minutos_intervalo = col_character(),
.default = col_integer()
))
return(dados)
}
# Função para importar dados mensais de lombadas
importar_lombadas_mensais <- function(mes) {
arquivo <- sprintf("%slomb2020.csv", mes)
dados <- read_delim(arquivo,
delim = ";",
locale = locale(decimal_mark = ","),
col_types = cols(
ano = col_integer(),
mes = col_character(),
equipamento = col_character(),
faixa = col_integer(),
data = col_date(format = ""),
hora = col_integer(),
minutos_intervalo = col_character(),
.default = col_integer()
))
return(dados)
}
# Importando o mês de janeiro para demonstração
fotossensores_janeiro <- importar_fotossensores_mensais("janeiro")
lombadas_janeiro <- importar_lombadas_mensais("janeiro")Foi criada uma abordagem funcional para importar os dados mensais,
permitindo tratar de forma padronizada arquivos com nomenclaturas
diferentes. Essa abordagem utiliza funções como sprintf()
para construir nomes de arquivos parametrizados e locale()
para lidar com as particularidades regionais de formatação numérica.
Vejamos como se apresentam as estruturas originais dos dados:
# Exibindo primeiras linhas dos dados
head(lombadas_fotossensores) %>%
kable(caption = "Tabela de Equipamentos (lombadas_fotossensores)") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "left") %>%
scroll_box(width = "100%", height = "300px") | equipamento | tipo | logradouro | velocidade_via | latitude | longitude |
|---|---|---|---|---|---|
| 5941 | Lombada | AV. MAL. MASCARENHAS DE MORAES, EM FRENTE AEROPORTO - SENT. PRAZERES | 60 | -81309702 | -349161612 |
| 5942 | Lombada | AV. MAL. MASCARENHAS DE MORAES, EM FRENTE AEROPORTO - SENT. CENTRO | 60 | -81306469 | -349158856 |
| 5943 | Lombada | AV. BOA VIAGEM - TERCEIRO JARDIM | 60 | -81078431 | -348881609 |
| 5944 | Lombada | DEFRONTE A PCA. GOV. PAULO GUERRA, CABANGA - SENT. PINA | 60 | -80801208 | -348921866 |
| 5945 | Lombada | APOS PONTE AGAMENON MAGALHAES, CABANGA - SENT. DERBY | 60 | -80808198 | -348911590 |
| 5946 | Lombada | AV. BOA VIAGEM – EM FRENTE PARQUE DONA LINDU | 60 | -81410665 | -349032775 |
head(fotossensores_janeiro, 3) %>%
kable(caption = "Dados de fotossensores (Janeiro 2020)") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "left") %>%
scroll_box(width = "100%", height = "300px") | mes | equipamento | faixa | data | hora | minutos_intervalo | qtd_0a10km | qtd_11a20km | qtd_21a30km | qtd_31a40km | qtd_41a50km | qtd_51a60km | qtd_61a70km | qtd_71a80km | qtd_81a90km | qtd_91a100km | qtd_acimade100km |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | FS002REC | 1 | 2020-01-01 | 0 | 0-15 | 1 | 2 | 8 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | FS002REC | 1 | 2020-01-01 | 0 | 16-30 | 0 | 8 | 8 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | FS002REC | 1 | 2020-01-01 | 0 | 31-45 | 0 | 12 | 21 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
head(lombadas_janeiro, 3) %>%
kable(caption = "Dados de lombadas (Janeiro 2020)") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "left") %>%
scroll_box(width = "100%", height = "300px") | ano | mes | equipamento | faixa | data | hora | minutos_intervalo | qtd_0a10km | qtd_11a20km | qtd_21a30km | qtd_31a40km | qtd_41a50km | qtd_51a60km | qtd_61a70km | qtd_71a80km | qtd_81a90km | qtd_91a100km | qtd_acimade100km |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2020 | 01 | 1 | 1 | 2020-01-01 | 10 | 10:00-10:15 | 0 | 2 | 1 | 7 | 25 | 13 | 0 | 0 | 0 | 0 | 0 |
| 2020 | 01 | 1 | 1 | 2020-01-01 | 10 | 10:15-10:30 | 0 | 0 | 0 | 6 | 9 | 8 | 0 | 0 | 0 | 0 | 0 |
| 2020 | 01 | 1 | 1 | 2020-01-01 | 10 | 10:30-10:45 | 1 | 0 | 2 | 9 | 13 | 7 | 0 | 0 | 0 | 0 | 0 |
Como podemos observar, os dados originais apresentam:
O primeiro desafio foi consolidar os 24 arquivos mensais (12 para fotossensores e 12 para lombadas) em uma única estrutura de dados. Para isso, foi criada uma função genérica para importar e padronizar os dados:
# Função para importar dados mensais
importar_dados_mensais <- function(tipo, mes) {
if(tipo == "fotossensores") {
arquivo <- sprintf("recife-fotossensores-20-%s.csv", mes)
dados <- read_delim(arquivo,
delim = ";",
locale = locale(decimal_mark = ",")) %>%
mutate(
mes = as.integer(mes),
equipamento = as.character(equipamento),
tipo_equipamento = str_to_title(tipo)
)
} else {
arquivo <- sprintf("%slomb2020.csv", mes)
dados <- read_delim(arquivo,
delim = ";",
locale = locale(decimal_mark = ",")) %>%
mutate(
mes = as.integer(mes),
equipamento = as.character(equipamento),
tipo_equipamento = tipo
)
}
return(dados)
}
# Lista de meses
meses <- c("janeiro", "fevereiro", "marco", "abril", "maio", "junho",
"julho", "agosto", "setembro", "outubro", "novembro", "dezembro")
# Importar todos os dados
dados_completos <- map_df(meses, function(mes) {
fotossensores <- tryCatch({
importar_dados_mensais("fotossensores", mes)
}, error = function(e) {
warning(sprintf("Erro ao importar fotossensores do mês %s: %s", mes, e$message))
return(NULL)
})
lombadas <- tryCatch({
importar_dados_mensais("lombadas", mes)
}, error = function(e) {
warning(sprintf("Erro ao importar lombadas do mês %s: %s", mes, e$message))
return(NULL)
})
bind_rows(fotossensores, lombadas)
}) %>%
# Limpeza do sufixo REC
mutate(equipamento = str_replace(equipamento, "REC$", ""))Esta abordagem utiliza programação funcional através da função
map_df() do pacote purrr, que aplica a mesma função a cada
elemento de uma lista (neste caso, cada mês) e combina os resultados em
um único data frame. Também foi implementado tratamento de erros com
tryCatch() para lidar com possíveis arquivos ausentes ou
corrompidos.
Um desafio significativo foi transformar os dados do formato “largo” original para um formato “longo”, mais adequado para análise. No formato original, cada faixa de velocidade é uma coluna separada, dificultando análises comparativas entre faixas.
# Transformação para formato longo
dados_longos <- dados_completos %>%
pivot_longer(
cols = starts_with("qtd_"),
names_to = "faixa_velocidade",
values_to = "quantidade_veiculos"
) %>%
mutate(
faixa_velocidade = case_when(
faixa_velocidade == "qtd_0a10km" ~ "0-10",
faixa_velocidade == "qtd_11a20km" ~ "11-20",
faixa_velocidade == "qtd_21a30km" ~ "21-30",
faixa_velocidade == "qtd_31a40km" ~ "31-40",
faixa_velocidade == "qtd_41a50km" ~ "41-50",
faixa_velocidade == "qtd_51a60km" ~ "51-60",
faixa_velocidade == "qtd_61a70km" ~ "61-70",
faixa_velocidade == "qtd_71a80km" ~ "71-80",
faixa_velocidade == "qtd_81a90km" ~ "81-90",
faixa_velocidade == "qtd_91a100km" ~ "91-100",
faixa_velocidade == "qtd_acimade100km" ~ ">100"
),
velocidade_media = case_when(
faixa_velocidade == "0-10" ~ 5,
faixa_velocidade == "11-20" ~ 15,
faixa_velocidade == "21-30" ~ 25,
faixa_velocidade == "31-40" ~ 35,
faixa_velocidade == "41-50" ~ 45,
faixa_velocidade == "51-60" ~ 55,
faixa_velocidade == "61-70" ~ 65,
faixa_velocidade == "71-80" ~ 75,
faixa_velocidade == "81-90" ~ 85,
faixa_velocidade == "91-100" ~ 95,
faixa_velocidade == ">100" ~ 110
),
periodo = case_when(
hora >= 0 & hora < 6 ~ "Madrugada",
hora >= 6 & hora < 12 ~ "Manhã",
hora >= 12 & hora < 18 ~ "Tarde",
hora >= 18 ~ "Noite"
),
dia_semana = factor(wday(data),
levels = 1:7,
labels = c("Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"))
)Este processo envolveu:
pivot_longer() para transformar as colunas de
faixas de velocidade em linhasvelocidade_media estimada para cada
faixaperiodo (parte
do dia) e dia_semanaPara permitir análises mais avançadas, foi necessário: 1. Mesclar os registros de velocidade com as informações de localização e velocidade regulamentada 2. Criar novas variáveis derivadas para análise de infrações
# Junção com dados de localização
dados_finais <- dados_longos %>%
left_join(lombadas_fotossensores, by = "equipamento") %>%
mutate(
acima_limite = velocidade_media > velocidade_via,
excesso_kmh = if_else(acima_limite, velocidade_media - velocidade_via, 0),
excesso_percentual = (velocidade_media / velocidade_via - 1) * 100
)Nesta etapa: 1. Utilizamos left_join() para mesclar os
dados de velocidade com as informações cadastrais dos equipamentos 2.
Criamos a variável booleana acima_limite para identificar
infrações 3. Calculamos métricas de excesso como
excesso_kmh (em km/h) e excesso_percentual
(percentual acima do limite)
Durante o processo de limpeza, foram identificados e tratados diversos casos de valores ausentes ou inconsistentes:
# Verificando e tratando valores ausentes no campo equipamento
dados_completos <- dados_completos %>%
mutate(equipamento = if_else(is.na(equipamento), "Não identificado", equipamento))
# Verificando quantidade de registros com informações ausentes
registros_incompletos <- dados_finais %>%
filter(is.na(tipo) | is.na(logradouro) | is.na(velocidade_via)) %>%
nrow()
cat("Registros com informações cadastrais incompletas:", registros_incompletos, "\n")## Registros com informações cadastrais incompletas: 18150
Os principais desafios encontrados e soluções adotadas foram:
Após todo o processo de transformação, o conjunto de dados final possui a seguinte estrutura:
# Visualização dos dados transformados
head(dados_finais) %>%
# select(data, hora, periodo, faixa_velocidade, quantidade_veiculos,
# logradouro, velocidade_via, acima_limite) %>%
kable(caption = "Dados Finais Transformados") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "left") %>%
scroll_box(width = "100%", height = "300px") | mes | equipamento | faixa | data | hora | minutos_intervalo | tipo_equipamento | ano | faixa_velocidade | quantidade_veiculos | velocidade_media | periodo | dia_semana | tipo | logradouro | velocidade_via | latitude | longitude | acima_limite | excesso_kmh | excesso_percentual |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 0-10 | 1 | 5 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | FALSE | 0 | -83.33333 |
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 11-20 | 2 | 15 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | FALSE | 0 | -50.00000 |
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 21-30 | 8 | 25 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | FALSE | 0 | -16.66667 |
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 31-40 | 2 | 35 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | TRUE | 5 | 16.66667 |
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 41-50 | 0 | 45 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | TRUE | 15 | 50.00000 |
| 1 | FS002 | 1 | 2020-01-01 | 0 | 0-15 | Fotossensores | NA | 51-60 | 0 | 55 | Madrugada | Qua | Fotossensor | RUA MADRE DE DEUS, SEMAFORO 020. | 30 | -80634002 | -348736694 | TRUE | 25 | 83.33333 |
O conjunto final de dados inclui: - Dimensões temporais: Data, hora, período do dia, dia da semana, mês - Localização: Equipamento, logradouro, coordenadas geográficas - Velocidade: Faixa de velocidade, velocidade média estimada, limite da via - Métricas de infração: Indicador de excesso, quantidade em km/h, percentual
A transformação de formato “largo” para “longo” resultou em uma explosão do número de linhas, saindo da casa dos 3 milhões de linhas para aproximadamente 38 milhões de linhas, mas proporcionou muito maior flexibilidade analítica. Cada registro agora representa o número de veículos em determinada faixa de velocidade, em determinado equipamento, durante um intervalo de 15 minutos.
É importante reconhecer algumas limitações inerentes a estes dados:
Estas limitações foram consideradas nas análises subsequentes e interpretação dos resultados.
# Estatísticas gerais
stats_gerais <- dados_finais %>%
summarise(
total_registros = n(),
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_equipamentos = n_distinct(equipamento),
media_diaria = round(total_veiculos / n_distinct(data), 0)
)
# Visualização das estatísticas
kable(stats_gerais,
format = "html",
caption = "Estatísticas Gerais dos Dados",
format.args = list(big.mark = ".")) %>%
kable_styling(bootstrap_options = c("striped", "hover"))| total_registros | total_veiculos | total_equipamentos | media_diaria |
|---|---|---|---|
| 38.601.079 | 278.364.052 | 70 | 758.485 |
# Preparar os dados para ambas as métricas
analise_horaria <- dados_finais %>%
filter(!is.na(hora)) %>%
group_by(hora) %>%
summarise(
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2),
.groups = 'drop'
)
# Determinar a proporção entre os eixos para visualização adequada
# Encontrar a proporção aproximada entre os valores máximos
proporcao <- max(analise_horaria$total_veiculos) / max(analise_horaria$total_infracoes)
# Versão alternativa com legenda em vez de cores nos títulos dos eixos
ggplot(analise_horaria) +
# Linha e pontos para infrações (eixo Y primário)
geom_line(aes(x = hora, y = total_infracoes, color = "Infrações"), size = 1.2) +
geom_point(aes(x = hora, y = total_infracoes, color = "Infrações"), size = 3) +
# Linha e pontos para volume total (eixo Y secundário)
geom_line(aes(x = hora, y = total_veiculos / proporcao, color = "Volume Total"), size = 1.2) +
geom_point(aes(x = hora, y = total_veiculos / proporcao, color = "Volume Total"), size = 3) +
# Configuração dos eixos
scale_y_continuous(
name = "Total de Infrações",
labels = scales::comma,
sec.axis = sec_axis(~.*proporcao, name = "Total de Veículos", labels = scales::comma)
) +
scale_x_continuous(breaks = 0:23) +
# Configuração de cores
scale_color_manual(values = c("Infrações" = "red", "Volume Total" = "blue")) +
# Estilo e títulos
theme_minimal() +
labs(
title = "Infrações e Volume de Veículos por Hora do Dia",
subtitle = "Distribuição ao longo do dia",
x = "Hora",
color = ""
) +
theme(
plot.title = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
panel.grid.major = element_line(color = "gray90"),
panel.grid.minor = element_line(color = "gray95"),
legend.position = "bottom"
)# Gráfico com percentual de infrações por hora - mantendo os valores nas barras
ggplot(analise_horaria) +
geom_col(aes(x = hora, y = percentual_infracoes, fill = percentual_infracoes),
width = 0.7) +
geom_text(aes(x = hora, y = percentual_infracoes,
label = paste0(format(percentual_infracoes, decimal.mark = ","), "%")),
vjust = -0.5, size = 3) +
scale_fill_gradient(low = "lightblue", high = "darkred") +
scale_x_continuous(breaks = 0:23) +
theme_minimal() +
guides(fill = "none") +
labs(title = "Percentual de Infrações por Hora do Dia",
subtitle = "Proporção de veículos que cometem infrações em cada horário",
x = "Hora",
y = "% de Infrações") +
theme(
plot.title = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)# Preparar os dados
analise_dia_semana <- dados_finais %>%
filter(!is.na(dia_semana)) %>%
group_by(dia_semana) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 1),
.groups = 'drop'
)
# Gráfico de barras principal com veículos
ggplot(analise_dia_semana) +
# Barras para total de veículos
geom_col(aes(x = dia_semana, y = total_veiculos), fill = "steelblue", alpha = 0.7) +
# Linha com percentual de infrações (eixo secundário)
geom_line(aes(x = dia_semana, y = total_veiculos * percentual_infracoes/100),
color = "red", size = 1.5, group = 1) +
geom_point(aes(x = dia_semana, y = total_veiculos * percentual_infracoes/100),
color = "red", size = 3) +
# Rótulos nas barras
geom_text(aes(x = dia_semana, y = total_veiculos,
label = scales::comma(total_veiculos)), vjust = -0.5) +
# Rótulos na linha percentual
geom_text(aes(x = dia_semana, y = total_veiculos * percentual_infracoes/100,
label = paste0(percentual_infracoes, "%")),
vjust = -0.8, color = "red", fontface = "bold") +
# Escalas e eixos
scale_y_continuous(
name = "Total de Veículos",
labels = scales::comma,
sec.axis = sec_axis(~.*100/max(analise_dia_semana$total_veiculos),
name = "% de Infrações", labels = function(x) paste0(round(x, 1), "%"))
) +
# Estilo e títulos
theme_minimal() +
labs(title = "Volume de Veículos e Percentual de Infrações por Dia da Semana",
subtitle = "Barras: total de veículos | Linha vermelha: percentual de infrações",
x = "Dia da Semana",
y = "Total de Veículos") +
theme(
plot.title = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
axis.title.y.right = element_text(color = "red"),
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 0, hjust = 0.5)
)# Análise por dia da semana
analise_semanal <- dados_finais %>%
filter(!is.na(dia_semana)) %>%
group_by(dia_semana, periodo) %>%
summarise(
media_veiculos = round(mean(quantidade_veiculos, na.rm = TRUE), 0),
media_infracoes = round(mean(quantidade_veiculos * acima_limite, na.rm = TRUE), 0),
.groups = 'drop'
)
# Gráfico de movimentação por dia e período - sem valores nas barras
ggplot(analise_semanal,
aes(x = dia_semana, y = media_veiculos, fill = periodo)) + # Corrigido: fill = periodo sem aspas
geom_col(position = "dodge") +
theme_minimal() +
scale_fill_viridis_d() +
scale_y_continuous(labels = scales::comma) +
labs(title = "Média de Veículos por Dia da Semana e Período",
x = "Dia da Semana",
y = "Média de Veículos",
fill = "Período") +
theme(
legend.position = "top",
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold")
)# Análise mensal
analise_mensal <- dados_finais %>%
filter(!is.na(mes)) %>%
mutate(
nome_mes = factor(month.abb[mes], levels = month.abb)
) %>%
group_by(mes, nome_mes) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2),
.groups = 'drop'
)
# Criar anotações para os períodos importantes
anotacoes <- data.frame(
mes = c(3, 4),
nome_mes = factor(c("Mar", "Apr"), levels = month.abb),
nota = c("Início das\nrestrições", "Início das\nrestrições"),
y_pos = c(0.9, 0.85)
)
# Gráfico 1: Tendência de movimentação e infrações em um único gráfico (layout vertical)
plot1 <- ggplot(analise_mensal) +
geom_line(aes(x = nome_mes, y = total_veiculos, group = 1), color = "blue", size = 1.2) +
geom_point(aes(x = nome_mes, y = total_veiculos), color = "blue", size = 3) +
geom_text(aes(x = nome_mes, y = total_veiculos, label = scales::comma(total_veiculos)),
vjust = -0.8, size = 3) +
# Adicionar linhas verticais para destacar períodos importantes
geom_vline(xintercept = which(month.abb == "Mar"), linetype = "dashed", alpha = 0.5) +
geom_text(data = anotacoes %>% filter(mes == 3),
aes(x = nome_mes, y = y_pos * max(analise_mensal$total_veiculos), label = nota),
size = 3.5, fontface = "bold") +
theme_minimal() +
scale_y_continuous(labels = scales::comma) +
labs(title = "Tendência de Movimentação ao Longo do Ano",
x = "", # Remover label do eixo X para o primeiro gráfico
y = "Total de Veículos") +
theme(
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold"),
plot.margin = margin(b = 0) # Reduzir margem inferior
)
plot2 <- ggplot(analise_mensal) +
geom_line(aes(x = nome_mes, y = total_infracoes, group = 1), color = "darkred", size = 1.2) +
geom_point(aes(x = nome_mes, y = total_infracoes), color = "darkred", size = 3) +
geom_text(aes(x = nome_mes, y = total_infracoes, label = scales::comma(total_infracoes)),
vjust = -0.8, size = 3) +
# Adicionar linhas verticais para destacar períodos importantes
geom_vline(xintercept = which(month.abb == "Mar"), linetype = "dashed", alpha = 0.5) +
geom_text(data = anotacoes %>% filter(mes == 4),
aes(x = nome_mes, y = y_pos * max(analise_mensal$total_infracoes), label = nota),
size = 3.5, fontface = "bold") +
theme_minimal() +
scale_y_continuous(labels = scales::comma) +
labs(title = "Tendência de Infrações ao Longo do Ano",
x = "Mês",
y = "Total de Infrações") +
theme(
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold"),
plot.margin = margin(t = 0) # Reduzir margem superior
)
# Combinar os dois gráficos em uma única visualização
gridExtra::grid.arrange(plot1, plot2, nrow = 2)Neste tópico estão sendo comparadas o valor percentual de infrações com relação ao volume de veículos na rua.
# Preparar dados para análise da correlação entre volume de tráfego e taxa de infrações
correlacao_volume_infracoes <- dados_finais %>%
filter(!is.na(mes)) %>%
mutate(
nome_mes = factor(month.abb[mes], levels = month.abb)
) %>%
group_by(mes, nome_mes) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2),
.groups = 'drop'
)
# Criar anotações para os períodos importantes
anotacoes <- data.frame(
mes = c(3, 4),
nome_mes = factor(c("Mar", "Apr"), levels = month.abb),
nota = c("Início das\nrestrições", "Lockdown\nmais severo"),
y_pos = rep(max(correlacao_volume_infracoes$percentual_infracoes) * 0.9, 2)
)
# Gráfico comparativo entre volume de tráfego e taxa de infrações por mês
ggplot() +
# Linha para o volume de veículos (eixo esquerdo)
geom_line(data = correlacao_volume_infracoes,
aes(x = nome_mes, y = total_veiculos, group = 1, color = "Volume de Tráfego"),
size = 1.2) +
geom_point(data = correlacao_volume_infracoes,
aes(x = nome_mes, y = total_veiculos, color = "Volume de Tráfego"),
size = 3) +
# Linha para o percentual de infrações (eixo direito)
geom_line(data = correlacao_volume_infracoes,
aes(x = nome_mes, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
group = 1, color = "% de Infrações"),
size = 1.2) +
geom_point(data = correlacao_volume_infracoes,
aes(x = nome_mes, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
color = "% de Infrações"),
size = 3) +
# Adicionar rótulos de dados
geom_text(data = correlacao_volume_infracoes,
aes(x = nome_mes,
y = total_veiculos,
label = scales::comma(total_veiculos)),
vjust = -0.8, size = 3, color = "darkblue") +
geom_text(data = correlacao_volume_infracoes,
aes(x = nome_mes,
y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
label = paste0(format(percentual_infracoes, decimal.mark = ","), "%")),
vjust = 1.8, size = 3, color = "darkred") +
# Linhas verticais para destacar o início da pandemia
geom_vline(xintercept = which(month.abb == "Mar"), linetype = "dashed", alpha = 0.5) +
# Destacar anotações importantes
geom_text(data = anotacoes,
aes(x = nome_mes, y = y_pos * max(correlacao_volume_infracoes$total_veiculos) / max(correlacao_volume_infracoes$percentual_infracoes),
label = nota),
size = 3.5, fontface = "bold") +
# Configurar eixos duplos
scale_y_continuous(
name = "Volume de Tráfego (veículos)",
labels = scales::comma,
sec.axis = sec_axis(~. * max(correlacao_volume_infracoes$percentual_infracoes) / max(correlacao_volume_infracoes$total_veiculos),
name = "Percentual de Infrações (%)")
) +
# Configurar cores
scale_color_manual(values = c("Volume de Tráfego" = "darkblue", "% de Infrações" = "darkred")) +
# Adicionar título e tema
labs(title = "Relação entre Volume de Tráfego e Taxa de Infrações durante 2020",
subtitle = "Análise do impacto da redução de tráfego devido à pandemia na taxa de infrações",
x = "Mês") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 12),
axis.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
legend.title = element_blank(),
legend.position = "top"
)# NOVO GRÁFICO 1: Análise por dia da semana
# Preparar dados para análise por dia da semana
correlacao_semanal <- dados_finais %>%
filter(!is.na(dia_semana)) %>%
group_by(dia_semana) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2),
.groups = 'drop'
)
# Gráfico comparativo entre volume de tráfego e taxa de infrações por dia da semana
ggplot() +
# Linha para o volume de veículos (eixo esquerdo)
geom_line(data = correlacao_semanal,
aes(x = dia_semana, y = total_veiculos, group = 1, color = "Volume de Tráfego"),
size = 1.2) +
geom_point(data = correlacao_semanal,
aes(x = dia_semana, y = total_veiculos, color = "Volume de Tráfego"),
size = 3) +
# Linha para o percentual de infrações (eixo direito)
geom_line(data = correlacao_semanal,
aes(x = dia_semana, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
group = 1, color = "% de Infrações"),
size = 1.2) +
geom_point(data = correlacao_semanal,
aes(x = dia_semana, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
color = "% de Infrações"),
size = 3) +
# Adicionar rótulos de dados
geom_text(data = correlacao_semanal,
aes(x = dia_semana,
y = total_veiculos,
label = scales::comma(total_veiculos)),
vjust = -0.8, size = 3, color = "darkblue") +
geom_text(data = correlacao_semanal,
aes(x = dia_semana,
y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
label = paste0(format(percentual_infracoes, decimal.mark = ","), "%")),
vjust = 1.8, size = 3, color = "darkred") +
# Configurar eixos duplos
scale_y_continuous(
name = "Volume de Tráfego (veículos)",
labels = scales::comma,
sec.axis = sec_axis(~. * max(correlacao_semanal$percentual_infracoes) / max(correlacao_semanal$total_veiculos),
name = "Percentual de Infrações (%)")
) +
# Configurar cores
scale_color_manual(values = c("Volume de Tráfego" = "darkblue", "% de Infrações" = "darkred")) +
# Adicionar título e tema
labs(title = "Relação entre Volume de Tráfego e Taxa de Infrações por Dia da Semana",
subtitle = "Análise do comportamento dos motoristas em diferentes dias da semana",
x = "Dia da Semana") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 12),
axis.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
legend.title = element_blank(),
legend.position = "top"
)# NOVO GRÁFICO 2: Análise por hora do dia
# Preparar dados para análise por hora
correlacao_horaria <- dados_finais %>%
filter(!is.na(hora)) %>%
group_by(hora) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2),
.groups = 'drop'
)
# Criar anotações para horários de pico
anotacoes_hora <- data.frame(
hora = c(8, 18),
nota = c("Pico\nmatutino", "Pico\nnoturno"),
y_pos = rep(max(correlacao_horaria$percentual_infracoes) * 0.9, 2)
)
# Gráfico comparativo entre volume de tráfego e taxa de infrações por hora
ggplot() +
# Linha para o volume de veículos (eixo esquerdo)
geom_line(data = correlacao_horaria,
aes(x = hora, y = total_veiculos, group = 1, color = "Volume de Tráfego"),
size = 1.2) +
geom_point(data = correlacao_horaria,
aes(x = hora, y = total_veiculos, color = "Volume de Tráfego"),
size = 3) +
# Linha para o percentual de infrações (eixo direito)
geom_line(data = correlacao_horaria,
aes(x = hora, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
group = 1, color = "% de Infrações"),
size = 1.2) +
geom_point(data = correlacao_horaria,
aes(x = hora, y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
color = "% de Infrações"),
size = 3) +
# Adicionar rótulos de dados apenas para alguns pontos para não sobrecarregar o gráfico
geom_text(data = correlacao_horaria %>%
filter(hora %in% c(0, 6, 8, 12, 15, 18, 21, 23)),
aes(x = hora,
y = total_veiculos,
label = scales::comma(total_veiculos)),
vjust = -0.8, size = 3, color = "darkblue") +
geom_text(data = correlacao_horaria %>%
filter(hora %in% c(0, 3, 6, 9, 12, 15, 18, 21, 23)),
aes(x = hora,
y = percentual_infracoes * max(total_veiculos) / max(percentual_infracoes),
label = paste0(format(percentual_infracoes, decimal.mark = ","), "%")),
vjust = 1.8, size = 3, color = "darkred") +
# Linhas verticais para destacar horários de pico
geom_vline(xintercept = c(8, 18), linetype = "dashed", alpha = 0.5) +
# Destacar anotações importantes
geom_text(data = anotacoes_hora,
aes(x = hora,
y = y_pos * max(correlacao_horaria$total_veiculos) / max(correlacao_horaria$percentual_infracoes),
label = nota),
size = 3.5, fontface = "bold") +
# Configurar eixos duplos
scale_y_continuous(
name = "Volume de Tráfego (veículos)",
labels = scales::comma,
sec.axis = sec_axis(~. * max(correlacao_horaria$percentual_infracoes) / max(correlacao_horaria$total_veiculos),
name = "Percentual de Infrações (%)")
) +
# Configurar eixo x com todas as horas
scale_x_continuous(breaks = 0:23) +
# Configurar cores
scale_color_manual(values = c("Volume de Tráfego" = "darkblue", "% de Infrações" = "darkred")) +
# Adicionar título e tema
labs(title = "Relação entre Volume de Tráfego e Taxa de Infrações por Hora do Dia",
subtitle = "Análise do comportamento dos motoristas em diferentes horários",
x = "Hora do Dia") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 12),
axis.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
legend.title = element_blank(),
legend.position = "top"
)# Distribuição das velocidades
dados_finais %>%
group_by(faixa_velocidade) %>%
summarise(total = sum(quantidade_veiculos, na.rm = TRUE)) %>%
ggplot(aes(x = faixa_velocidade, y = total)) +
geom_col(fill = "darkred") +
geom_text(aes(label = scales::comma(total)), vjust = -0.5) +
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Distribuição de Velocidades",
x = "Faixa de Velocidade (km/h)",
y = "Total de Veículos")# Análise de infrações
dados_finais %>%
group_by(tipo_equipamento) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
veiculos_acima = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
percentual_acima = round(veiculos_acima / total_veiculos * 100, 2)
) %>%
kable(
format = "html",
caption = "Percentual de Infrações por Tipo de Equipamento",
format.args = list(big.mark = ".", decimal.mark = ",")
) %>%
kable_styling(bootstrap_options = c("striped", "hover"))| tipo_equipamento | total_veiculos | veiculos_acima | percentual_acima |
|---|---|---|---|
| Fotossensores | 78.313.456 | 907.731 | 1,16 |
| lombadas | 200.050.596 | 2.621.959 | 1,31 |
# Análise de infrações por local em formato de tabela
infracoes_local <- dados_finais %>%
filter(!is.na(logradouro)) %>%
group_by(logradouro) %>%
summarise(
total_veiculos = sum(quantidade_veiculos, na.rm = TRUE),
total_infracoes = sum(quantidade_veiculos * acima_limite, na.rm = TRUE),
velocidade_via = max(velocidade_via, na.rm = TRUE),
qtd_faixas = max(faixa, na.rm = TRUE),
.groups = 'drop'
) %>%
mutate(
percentual_infracoes = round((total_infracoes / total_veiculos) * 100, 2)
) %>%
arrange(desc(percentual_infracoes))
# Exibição em formato de tabela
kable(infracoes_local,
format = "html",
col.names = c("Local", "Total de Veículos", "Total de Infrações", "Velocidade da Via (km/h)" ,"Qtd. Faixas", "Percentual de Infrações (%)"),
caption = "Infrações por Local",
format.args = list(big.mark = ".", decimal.mark = ",")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = TRUE) %>%
row_spec(0, bold = TRUE) %>%
column_spec(1, width = "30%") %>%
column_spec(4, color = "white",
background = spec_color(infracoes_local$percentual_infracoes,
end = 0.7,
option = "D",
direction = 1))| Local | Total de Veículos | Total de Infrações | Velocidade da Via (km/h) | Qtd. Faixas | Percentual de Infrações (%) |
|---|---|---|---|---|---|
| RUA ARQ. LUIZ NUNES CRUZAMENTO RUA DEOLINDO TAVARES, SENT. SUBURBIO | 3.422.551 | 203.905 | 40 | 2 | 5,96 |
| RUA MADRE DE DEUS, SEMAFORO 020. | 2.012.098 | 95.223 | 30 | 3 | 4,73 |
| AV. MARQUES DE OLINDA, SEMAFORO 020. | 375.190 | 17.379 | 30 | 2 | 4,63 |
| RUA GUILHERME PINTO, SEMAFORO 432. | 1.240.836 | 51.894 | 40 | 2 | 4,18 |
| AV. DOM JOAO VI, ENTRE OS N. 777 E 835 - SENT. CENTRO | 5.150.262 | 167.120 | 50 | 2 | 3,24 |
| AV. ENG. ABDIAS DE CARVALHO, ENTRE OS N. 1785 E 1745 - SENT. CENTRO | 6.264.079 | 178.544 | 60 | 2 | 2,85 |
| AV. MARECHAL MASCARENHAS DE MORAES, SEMAFORO 530/531. | 2.644.262 | 69.514 | 60 | 4 | 2,63 |
| RUA REAL DA TORRE, SEMAFORO 237. | 1.341.253 | 33.678 | 50 | 3 | 2,51 |
| AV. ALFREDO LISBOA, ENTRE OS N. 33 E 18 | 5.097.902 | 126.620 | 30 | 2 | 2,48 |
| AV. CDE. DA BOA VISTA, SEMAFORO 486. | 1.299.247 | 32.234 | 40 | 4 | 2,48 |
| AV. DOM JOAO VI, EM FRT. AO PT. DE ONIBUS N. 010243, IMBIRIBEIRA | 4.700.308 | 107.869 | 50 | 2 | 2,29 |
| AV. ENG. ABDIAS DE CARVALHO, SEMAFORO 271. | 2.392.082 | 50.682 | 60 | 3 | 2,12 |
| AV. CELSO FURTADO KM 1,5 - SENT. CENTRO | 7.439.160 | 144.998 | 60 | 2 | 1,95 |
| AV. MAL. MASCARENHAS DE MORAES, EM FRENTE AEROPORTO - SENT. CENTRO | 10.384.754 | 196.573 | 60 | 4 | 1,89 |
| AV. BEBERIBE, 3101 - SENT. CENTRO | 6.983.041 | 113.924 | 50 | 2 | 1,63 |
| AV. REPUBLICA DO LIBANO, N. 115 - PINA - SENT. SUBURBIO | 9.647.536 | 149.593 | 60 | 3 | 1,55 |
| AV. ENG. ABDIAS DE CARVALHO, SEMAFORO 328. | 3.012.398 | 46.524 | 60 | 4 | 1,54 |
| RUA CONEGO BARATA, 55 - SENTIDO TORRE | 3.371.746 | 50.396 | 50 | 2 | 1,49 |
| AV. BOA VIAGEM, SEMAFORO 104. | 2.977.494 | 43.871 | 60 | 4 | 1,47 |
| AV. GOV. AGAMENON MAGALHAES – PROX. VIADUTO PRES. MEDICI - SENT. DERBY | 8.706.159 | 120.406 | 60 | 4 | 1,38 |
| AV. DR. JOSE RUFINO, SEMAFORO 082. | 850.105 | 11.597 | 60 | 4 | 1,36 |
| AV. GOV. AGAMENON MAGALHAES – EM FRENTE REITORIA UPE - SENT. OLINDA | 12.500.080 | 160.447 | 60 | 2 | 1,28 |
| AV. MAL. MASCARENHAS DE MORAES, EM FRENTE AEROPORTO - SENT. PRAZERES | 12.798.869 | 157.293 | 60 | 4 | 1,23 |
| AV. LIBERDADE, SEMAFORO 440 | 1.132.482 | 12.600 | 50 | 2 | 1,11 |
| RUA FALCAO DE LACERDA SEMAFORO 285 | 3.016.398 | 32.561 | 50 | 2 | 1,08 |
| AV. RECIFE, SEMAFORO 617. | 3.039.101 | 31.198 | 60 | 3 | 1,03 |
| AV. ENG. DOMINGOS FERREIRA, SEMAFORO 297. | 4.169.440 | 42.051 | 60 | 4 | 1,01 |
| AV. SATURNINO DE BRITO - PROX. A COMPESA, SENT. SUBURBIO | 4.292.221 | 43.043 | 60 | 2 | 1,00 |
| AV. RECIFE, SEMAFORO 336. | 2.093.155 | 20.467 | 60 | 3 | 0,98 |
| AV. BEBERIBE, 2960 - SENT. SUBÚRBIO | 5.573.743 | 53.254 | 50 | 2 | 0,96 |
| AV. DESEMBARGADOR JOSÉ NEVES, SEMAFORO 400 | 3.566.954 | 33.919 | 50 | 2 | 0,95 |
| PONTE DELMIRO GOUVEIA, SEMAFORO 075. | 254.715 | 2.349 | 50 | 2 | 0,92 |
| RUA VISCONDE DE JEQUITINHONHA,SEMAFORO 158 | 6.331.409 | 57.916 | 60 | 4 | 0,91 |
| AV. BOA VIAGEM - TERCEIRO JARDIM | 6.402.919 | 56.845 | 60 | 3 | 0,89 |
| CAIS SANTA RITA, PROX. AO N. 675 - SENT. CENTRO | 7.922.201 | 70.436 | 60 | 2 | 0,89 |
| AV. CONS. AGUIAR, N. 4620 | 2.266.284 | 19.366 | 60 | 2 | 0,85 |
| AV. CELSO FURTADO KM 2,4 - SENT. SUBURBIO | 7.039.102 | 59.028 | 60 | 2 | 0,84 |
| AV. GENERAL SAN MARTIN, N. 1864, SENT. AV. RECIFE | 6.164.783 | 49.965 | 40 | 2 | 0,81 |
| AV. ENG. DOMINGOS FERREIRA, SEMAFORO 338. | 2.271.213 | 18.053 | 60 | 4 | 0,79 |
| AV. BOA VIAGEM – EM FRENTE PARQUE DONA LINDU | 8.882.796 | 68.121 | 60 | 2 | 0,77 |
| AV. ENG. JOSÉ ESTELITA - ENTRE PTS. DE ILUM. 19-R e 21-R, SENT. CENTRO | 4.280.428 | 32.329 | 60 | 2 | 0,76 |
| AV. AFONSO OLINDENSE, N. 996, SENT. CAXANGA | 4.013.849 | 29.345 | 40 | 2 | 0,73 |
| AV. ENG. ANTONIO DE GOES, N. 124 | 5.203.000 | 38.051 | 60 | 2 | 0,73 |
| AV. DESEMBARGADOR JOSÉ NEVES, SEMAFORO 580 | 2.887.116 | 20.539 | 50 | 2 | 0,71 |
| AV. GOV. AGAMENON MAGALHAES, SEMAFORO 173. | 4.220.419 | 29.338 | 60 | 4 | 0,70 |
| AV. ENG. ABDIAS DE CARVALHO, SEMAFORO 272. | 2.229.180 | 15.425 | 60 | 3 | 0,69 |
| APOS PONTE AGAMENON MAGALHAES, CABANGA - SENT. DERBY | 11.113.061 | 74.764 | 60 | 2 | 0,67 |
| AV. GOV. AGAMENON MAGALHAES, SEMAFORO 069. | 2.919.624 | 19.208 | 60 | 4 | 0,66 |
| AV. HERCULANO BANDEIRA, SEMAFORO 137. | 9.138.414 | 58.924 | 60 | 4 | 0,64 |
| AV. CELSO FURTADO KM 2,5 - SENT. CENTRO | 5.791.112 | 36.683 | 60 | 2 | 0,63 |
| AV.NORTE MIGUEL ARRAES DE ALENCAR, SEMAFORO 424 | 3.753.486 | 21.371 | 60 | 2 | 0,57 |
| AV. GOV. AGAMENON MAGALHAES, SEMAFORO 069 | 4.061.483 | 22.877 | 60 | 4 | 0,56 |
| AV. RUI BARBOSA, N. 1397 | 5.848.450 | 31.080 | 60 | 2 | 0,53 |
| DEFRONTE A PCA. GOV. PAULO GUERRA, CABANGA - SENT. PINA | 8.423.660 | 43.851 | 60 | 2 | 0,52 |
| AV. DEZESSETE DE AGOSTO, SEMAFORO 370. | 2.497.391 | 10.625 | 60 | 4 | 0,43 |
| RUA PARIS, PRÓXIMO A PARADA DE ÔNIBUS N.020470 | 4.404.278 | 18.466 | 50 | 2 | 0,42 |
| AV. MAURICIO DE NASSAU ENTRONCAMENTO 1a. TRV. SANTA LÚCIA, SENT. CENTRO | 5.794.386 | 19.644 | 40 | 2 | 0,34 |
| RUA PROF. ARNALDO CARNEIRO LEAO, SEMAFORO 544. | 1.468.387 | 3.660 | 60 | 3 | 0,25 |
| AV. BEBERIBE, SEMAFORO 131. | 1.118.124 | 2.054 | 60 | 2 | 0,18 |
A análise exploratória dos dados de fiscalização eletrônica em Recife revelou padrões significativos no comportamento dos motoristas e na eficácia dos sistemas de monitoramento:
Correlação Inversa entre Volume de Tráfego e Infrações: Um dos achados mais relevantes deste estudo é a clara relação inversa entre o volume de veículos e o percentual de infrações. Em múltiplos contextos temporais, observamos que quando o fluxo de veículos diminui, o percentual de infrações aumenta significativamente:
Este padrão sugere que a percepção de vias livres pode induzir comportamentos de maior risco, com motoristas aproveitando a ausência de congestionamentos para exceder os limites de velocidade.
Padrões Temporais Distintos: Os dados demonstram uma clara variação no volume de tráfego e nas infrações ao longo do dia, semana e ano. As primeiras horas da manhã apresentam os maiores percentuais de infrações, apesar do baixo volume de veículos. Durante o período diurno, o volume de tráfego aumenta significativamente enquanto o percentual de infrações cai para menos de 1%.
Impacto da Pandemia como Experimento Natural: O gráfico de tendência mensal evidencia uma queda acentuada no volume de tráfego a partir de março, coincidindo com o “Início das restrições” devido à pandemia. Esta situação funcionou como um experimento natural que corroborou a hipótese da correlação inversa entre volume e infrações - quando as vias esvaziaram, o comportamento de risco aumentou proporcionalmente.
Padrão Semanal: Os dias úteis (segunda a sexta) apresentam volumes de tráfego similares, com queda significativa nos finais de semana, especialmente aos domingos. O percentual de infrações, entretanto, é mais alto aos domingos, reforçando o padrão identificado.
Distribuição de Velocidades: A maior concentração de veículos trafega na faixa de velocidade de 40-50 km/h, seguida pela faixa de 30-40 km/h. Isso sugere que a maioria dos motoristas respeita os limites estabelecidos nas vias urbanas de Recife.
Eficácia dos Equipamentos: Os fotossensores detectaram infrações em 1,16% dos veículos monitorados, enquanto as lombadas eletrônicas registraram 1,31%. Esta diferença pode indicar variações na eficácia ou nas características das vias.
Pontos Críticos: Identificamos locais com percentuais de infração significativamente acima da média, como a Rua Madre de Deus (4,73%) e a Av. Marquês de Olinda (4,63%), ambas com limite de 30 km/h.
Nossos resultados sugerem diversas abordagens que poderiam aumentar a eficácia das políticas de segurança viária em Recife:
Fiscalização adaptativa baseada no volume: Implementar estratégias de fiscalização que considerem as condições de fluxo de veículos, intensificando a presença em períodos de baixo volume (madrugadas, domingos e situações excepcionais como lockdowns), quando o comportamento de risco aumenta significativamente.
Intervenções específicas: Implementar medidas de moderação de tráfego nos pontos críticos identificados, como a Rua Madre de Deus e Av. Marquês de Olinda, que podem incluir desde campanhas educativas até intervenções físicas no desenho urbano.
Medidas automáticas para períodos de baixo fluxo: Considerar a implementação de redutores de velocidade físicos ou temporários e radares adaptativos que possam ser intensificados em períodos de menor fluxo.
Campanhas educativas direcionadas: Desenvolver mensagens específicas sobre os riscos associados ao excesso de velocidade em vias menos congestionadas, focando nos horários e locais de maior incidência de infrações.
Avaliação de equipamentos: Realizar estudos complementares sobre a eficácia comparativa entre fotossensores e lombadas eletrônicas, considerando as características específicas das vias onde estão instalados.
Este estudo contribui para o campo da segurança viária de várias formas:
Abordagem baseada em evidências: Nossa análise fornece evidências quantitativas sobre padrões reais de velocidade e comportamento no trânsito, superando percepções anedóticas.
Identificação da correlação inversa tráfego-infração: A clara demonstração de que períodos e locais com menor volume de tráfego apresentam maiores índices de infração oferece um insight valioso para a elaboração de políticas públicas mais eficazes.
Granularidade temporal: A análise por períodos do dia, dias da semana e meses do ano permite identificar padrões cíclicos que podem orientar políticas temporalmente dirigidas.
Impacto da pandemia como experimento natural: As restrições de mobilidade durante a pandemia proporcionaram um cenário único para observar como a redução significativa do volume de tráfego afeta o comportamento dos motoristas.
Identificação de hot spots: O mapeamento de pontos críticos possibilita a priorização de intervenções onde o impacto pode ser maximizado.
Para os gestores da mobilidade urbana do Recife, estes insights fornecem um valioso subsídio para a tomada de decisões baseadas em dados, potencialmente contribuindo para a redução de acidentes e a preservação de vidas.
É importante reconhecer algumas limitações que contextualizem adequadamente nossos resultados:
Período atípico: Os dados de 2020 foram significativamente influenciados pela pandemia de COVID-19, com mudanças drásticas nos padrões de mobilidade urbana a partir de março.
Ausência de dados contextuais: Não tivemos acesso a dados sobre acidentes e fatalidades, o que limitou nossa capacidade de correlacionar infrações com desfechos de segurança.
Variáveis socioeconômicas: Não foram consideradas variáveis socioeconômicas que possam influenciar os padrões de tráfego e comportamento dos motoristas em diferentes regiões da cidade.
Fatores psicológicos: A análise quantitativa não captura os fatores psicológicos que levam motoristas a aumentar a velocidade quando as vias estão mais livres.
Baseado em nossas descobertas e limitações, sugerimos algumas direções promissoras para pesquisas futuras:
Análise espacial detalhada: Utilizar técnicas de georreferenciamento para identificar clusters de infrações e correlacioná-los com características específicas das vias.
Correlação com acidentes: Integrar dados de acidentes de trânsito para quantificar a relação entre infrações de velocidade e desfechos de segurança viária.
Experimentos controlados: Testar intervenções específicas em períodos de baixo fluxo para avaliar sua eficácia na redução de infrações.
Modelos preditivos: Desenvolver modelos que incorporem a variável de volume de tráfego para antecipar comportamentos de risco em diferentes cenários.
Estudos comparativos: Realizar comparações com outras capitais brasileiras para identificar se o padrão de correlação inversa entre volume e infrações é consistente em diferentes contextos urbanos.
Análise de custo-benefício: Avaliar diferentes estratégias de fiscalização adaptadas aos padrões de volume de tráfego para determinar a abordagem mais eficiente.
A continuidade deste tipo de análise, especialmente com a integração de outras fontes de dados e perspectivas disciplinares, tem o potencial de contribuir significativamente para a construção de um sistema de mobilidade mais seguro e eficiente para o Recife.