A mobilidade urbana representa um dos maiores desafios das cidades contemporâneas. Em Recife — cidade com malha viária complexa, alta densidade demográfica e frota veicular em crescimento contínuo —, compreender os padrões de circulação é fundamental para a tomada de decisões estratégicas. Este projeto analisa os dados de monitoramento eletrônico de velocidade das vias do município, coletados pela Autarquia de Trânsito e Transporte Urbano (CTTU) ao longo de todo o mês de janeiro de 2025.
A base utilizada, “Velocidade das Vias — Quantitativo por
Velocidade Média — Janeiro 2025”, é disponibilizada
publicamente pelo Portal de
Dados Abertos da Prefeitura do Recife. O dataset contém
283.999 registros e 18 colunas,
capturados por radares instalados nas principais vias da cidade. As
variáveis centrais para esta análise são o momento do registro
(data_hora), o ponto de monitoramento
(local_equipamento) e a velocidade média registrada
(velocidade_media).
Como o problema será abordado:
Os dados utilizados são os registros de janeiro de 2025 disponibilizados pelo Portal de Dados Abertos da Prefeitura do Recife, coletados automaticamente pelos equipamentos eletrônicos da CTTU a cada 15 minutos. O pipeline analítico é organizado em três etapas sequenciais e interdependentes:
;, conversão de tipos, derivação das
variáveis volume_veiculos (soma das 11 faixas de
velocidade) e velocidade_media (média ponderada pelos
pontos médios de cada faixa), e decomposição temporal em
hora, dia_semana e tipo_dia;ggplot2 convertidos para HTML interativo com
ggplotly() e tabelas dinâmicas com DT,
permitindo exploração ativa dos dados pelo leitor.Técnica adotada e sua justificativa:
A técnica central é a Análise Exploratória de Dados (EDA) — abordagem não paramétrica que prioriza a descoberta de padrões por meio de agregações, comparações e visualizações, sem pressupor um modelo estatístico prévio. A escolha se justifica pela natureza do problema: os dados de vigilância eletrônica são densos (283.999 registros, resolução de 15 minutos) e o objetivo não é testar hipóteses, mas revelar estruturas latentes nos padrões de circulação urbana.
As operações técnicas centrais incluem:
volume_veiculos,
velocidade_media);hora, tipo_dia e
local_equipamento reduzem ~283 mil registros a sumários
comparáveis e acionáveis;Os insights gerados têm aplicação direta para a CTTU e gestores de mobilidade urbana, possibilitando:
Os pacotes abaixo foram selecionados para cobrir todas as etapas do pipeline: importação, manipulação, visualização e apresentação dos dados.
library(tidyverse) # Manipulação e visualização de dados (dplyr, ggplot2, readr, tidyr...)
library(lubridate) # Operações com datas e horas de forma simplificada
library(plotly) # Conversão de gráficos ggplot2 em visualizações HTML interativas
library(DT) # Tabelas HTML interativas com paginação, busca e rolagem
tidyverse: Ecossistema coeso de
pacotes que provê uma gramática unificada para leitura
(readr), manipulação (dplyr,
tidyr) e visualização (ggplot2) de dados,
seguindo os princípios de tidy data.lubridate: Simplifica operações com
objetos POSIXct/Date — essencial para extrair
componentes como hora, dia da semana e mês a partir de campos datetime
sem ambiguidade.plotly: Permite converter qualquer
gráfico ggplot2 em uma visualização HTML interativa com uma
única chamada a ggplotly(), adicionando automaticamente
tooltips, zoom e filtragem por legenda.DT: Gera tabelas HTML baseadas na
biblioteca JavaScript DataTables, com suporte a paginação,
busca em tempo real e rolagem horizontal — ideal para exibir grandes
datasets em relatórios RMarkdown publicados no RPubs.Os dados provêm do Portal de Dados Abertos da Prefeitura do Recife, acessível em dados.recife.pe.gov.br. O dataset específico utilizado é o “Velocidade das Vias — Quantitativo por Velocidade Média — Janeiro 2025”, disponível para download gratuito sem necessidade de cadastro.
Propósito original: O dataset foi produzido pelo sistema de monitoramento eletrônico da CTTU para fins de fiscalização de velocidade e planejamento de mobilidade urbana. Cada equipamento (lombada eletrônica ou radar) registra automaticamente, a cada intervalo de 15 minutos, a quantidade de veículos detectados em cada faixa de velocidade por sentido de pista.
Período e granularidade: Os dados cobrem
integralmente o mês de janeiro de 2025, com registros a
cada 15 minutos (coluna
minutos_intervalo). Janeiro é um mês atípico por coincidir
com o período de férias escolares, o que influencia o perfil de tráfego
— o que torna a análise deste período particularmente interessante.
Estrutura original — 18 colunas:
| Grupo | Colunas | Descrição |
|---|---|---|
| Identificação temporal | ano, mes, data,
hour, minutos_intervalo |
Ano, mês, data, hora inteira e intervalo de 15 min |
| Identificação do ponto | equipamento, faixa |
Código do radar e sentido da faixa monitorada |
| Contagens por velocidade | qtd_0a10km até qtd_acimade100km |
11 colunas com contagem de veículos em cada faixa de velocidade |
Peculiaridades dos dados de origem — relevantes para a limpeza:
;
(ponto-e-vírgula) em vez de ,, exigindo
read_csv2() em lugar de read_csv();"" em vez de NA nativo
do R — requerem suppressWarnings(as.integer(.)) seguido de
replace_na(..., 0L) para tratamento correto;data e hour),
necessitando reconstrução via
ymd_h(paste(data, hora_csv));hour colide com a função lubridate::hour(),
exigindo renomeação prévia para hora_csv antes de qualquer
mutate();O arquivo CSV utiliza ponto-e-vírgula como separador
(padrão de exportação do portal do Recife) e está estruturado no formato
largo: cada linha representa um intervalo de 15 minutos
em um equipamento/faixa, com 11 colunas de contagem por faixa de
velocidade (qtd_0a10km até
qtd_acimade100km). A partir dessas colunas derivamos duas
variáveis analíticas essenciais:
volume_veiculos: soma total de
veículos em todos os intervalos de velocidade;velocidade_media: média ponderada pelo
ponto médio de cada faixa (ex.: 5 km/h para 0–10 km/h, 15,5 km/h para
11–20 km/h, etc.).A coluna data_hora é reconstituída combinando os campos
data e hour do CSV original.
# Leitura com separador ";" (read_csv2) e todas as colunas como caractere
dados_brutos <- read_csv2(
"lombadas-2025-janeiro-quantitativo-das-vias-por-velocidade-media.csv",
locale = locale(encoding = "UTF-8"),
col_types = cols(.default = col_character())
) %>%
# Renomeia "hour" para evitar conflito com lubridate::hour()
rename(hora_csv = hour) %>%
# Converte colunas de contagem por faixa: vazio/"" → 0, depois inteiro
mutate(across(
starts_with("qtd_"),
~ replace_na(suppressWarnings(as.integer(.)), 0L)
)) %>%
mutate(
# ── Variáveis derivadas ───────────────────────────────────────────────────
# Volume total: soma das 11 faixas de velocidade
volume_veiculos = rowSums(across(starts_with("qtd_")), na.rm = TRUE),
# Velocidade média ponderada pelos pontos médios de cada faixa (km/h)
velocidade_media = round(
(qtd_0a10km * 5.0 + qtd_11a20km * 15.5 +
qtd_21a30km * 25.5 + qtd_31a40km * 35.5 +
qtd_41a50km * 45.5 + qtd_51a60km * 55.5 +
qtd_61a70km * 65.5 + qtd_71a80km * 75.5 +
qtd_81a90km * 85.5 + qtd_91a100km * 95.5 +
qtd_acimade100km * 105.0) /
if_else(volume_veiculos == 0L, NA_real_, as.double(volume_veiculos)),
1
),
# Datetime: combina "data" (YYYY-MM-DD) com "hora_csv" (0–23)
data_hora = ymd_h(paste(data, hora_csv), tz = "America/Recife"),
local_equipamento = equipamento
# ─────────────────────────────────────────────────────────────────────────
) %>%
# Remove intervalos sem veículos ou com velocidade indeterminada
filter(volume_veiculos > 0L, !is.na(velocidade_media))
cat("Dimensões após limpeza inicial:", nrow(dados_brutos), "linhas ×",
ncol(dados_brutos), "colunas\n")
## Dimensões após limpeza inicial: 283997 linhas × 22 colunas
Com os dados derivados no bloco anterior, criamos as variáveis temporais necessárias para as análises. As etapas incluem:
hora e semana_mes a partir do
data_hora já parseado;dia_semana recebe rótulos em português via fator ordenado,
independentemente do locale do sistema;tipo_dia
categoriza cada registro como “Dia Útil” (segunda a sexta) ou
“Final de Semana” (sábado e domingo), variável central para a
terceira análise.dados <- dados_brutos %>%
mutate(
# data_hora já é POSIXct (criado em preparacao); apenas extraímos componentes
hora = hour(data_hora),
# Rótulos em português independente do locale do sistema
dia_semana = factor(
wday(data_hora, week_start = 1),
levels = 1:7,
labels = c("Segunda", "Terça", "Quarta", "Quinta",
"Sexta", "Sábado", "Domingo")
),
mes = factor(
month(data_hora),
levels = 1:12,
labels = c("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
"Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro")
),
tipo_dia = if_else(
wday(data_hora, week_start = 1) %in% 1:5,
"Dia Útil",
"Final de Semana"
),
semana_mes = paste0("Semana ", ceiling(day(data_hora) / 7))
)
glimpse(dados)
## Rows: 283,997
## Columns: 26
## $ ano <chr> "2025", "2025", "2025", "2025", "2025", "2025", "202…
## $ mes <fct> Janeiro, Janeiro, Janeiro, Janeiro, Janeiro, Janeiro…
## $ equipamento <chr> "CTTU-9111", "CTTU-9111", "CTTU-9111", "CTTU-9111", …
## $ faixa <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A…
## $ data <chr> "2025-01-11", "2025-01-11", "2025-01-11", "2025-01-1…
## $ hora_csv <chr> "12", "12", "12", "12", "13", "13", "13", "13", "14"…
## $ minutos_intervalo <chr> "12:00-12:15", "12:15-12:30", "12:30-12:45", "12:45-…
## $ qtd_0a10km <int> 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ qtd_11a20km <int> 7, 11, 9, 0, 6, 16, 6, 2, 1, 0, 1, 5, 0, 3, 5, 3, 4,…
## $ qtd_21a30km <int> 89, 90, 89, 69, 85, 81, 84, 78, 63, 67, 87, 81, 80, …
## $ qtd_31a40km <int> 32, 26, 56, 46, 53, 41, 54, 44, 48, 70, 52, 39, 39, …
## $ qtd_41a50km <int> 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1…
## $ qtd_51a60km <int> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0…
## $ qtd_61a70km <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ qtd_71a80km <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ qtd_81a90km <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ qtd_91a100km <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ qtd_acimade100km <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ volume_veiculos <dbl> 130, 130, 154, 116, 145, 139, 144, 124, 113, 137, 14…
## $ velocidade_media <dbl> 27.8, 26.2, 28.6, 29.6, 28.9, 27.4, 28.8, 28.9, 29.8…
## $ data_hora <dttm> 2025-01-11 12:00:00, 2025-01-11 12:00:00, 2025-01-1…
## $ local_equipamento <chr> "CTTU-9111", "CTTU-9111", "CTTU-9111", "CTTU-9111", …
## $ hora <int> 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, …
## $ dia_semana <fct> Sábado, Sábado, Sábado, Sábado, Sábado, Sábado, Sába…
## $ tipo_dia <chr> "Final de Semana", "Final de Semana", "Final de Sema…
## $ semana_mes <chr> "Semana 2", "Semana 2", "Semana 2", "Semana 2", "Sem…
A tabela abaixo exibe os primeiros 100 registros do dataset, ordenados por data e hora. Utilize a barra de busca, a paginação e a rolagem horizontal para explorar os dados interativamente:
DT::datatable(
dados %>% arrange(data_hora) %>% head(100),
caption = "Tabela 1 — Amostra dos Dados Processados (100 primeiros registros)",
rownames = FALSE,
class = "stripe hover",
options = list(
pageLength = 5,
scrollX = TRUE,
language = list(
search = "Buscar:",
info = "Mostrando _START_ a _END_ de _TOTAL_ registros",
paginate = list(previous = "Anterior", `next` = "Próximo"),
lengthMenu = "Exibir _MENU_ registros por página"
)
)
)
O dataset final contém 283,997 registros válidos, distribuídos ao longo de 37 equipamentos de monitoramento. A tabela abaixo consolida as principais características das variáveis analíticas utilizadas nas seções seguintes:
resumo_vars <- tibble(
`Variável` = c("data_hora", "local_equipamento", "volume_veiculos",
"velocidade_media", "hora", "dia_semana", "tipo_dia"),
`Tipo` = c("POSIXct", "character", "integer",
"double", "integer", "factor (7 níveis)", "factor (2 níveis)"),
`Descrição` = c(
"Timestamp do intervalo de 15 minutos",
"Código do equipamento de monitoramento",
"Total de veículos no intervalo (soma das 11 faixas)",
"Velocidade média ponderada pelos pontos médios das faixas (km/h)",
"Hora do dia extraída de data_hora (0–23)",
"Dia da semana em português (Segunda a Domingo)",
"Classificação do dia: Dia Útil ou Final de Semana"
),
`Faixa / Categorias` = c(
paste0(format(min(dados$data_hora), "%d/%m"), " a ",
format(max(dados$data_hora), "%d/%m/%Y")),
paste0(n_distinct(dados$local_equipamento), " equipamentos únicos"),
paste0(min(dados$volume_veiculos), " a ",
scales::comma(max(dados$volume_veiculos)),
" (mediana: ", median(dados$volume_veiculos), ")"),
paste0(round(min(dados$velocidade_media, na.rm = TRUE), 1), " a ",
round(max(dados$velocidade_media, na.rm = TRUE), 1), " km/h",
" (média: ", round(mean(dados$velocidade_media, na.rm = TRUE), 1), ")"),
"0 a 23",
"Segunda, Terça, Quarta, Quinta, Sexta, Sábado, Domingo",
paste0(scales::comma(sum(dados$tipo_dia == "Dia Útil")), " registros úteis / ",
scales::comma(sum(dados$tipo_dia == "Final de Semana")), " FdS")
)
)
knitr::kable(
resumo_vars,
align = "llll",
caption = "Tabela 2 — Resumo das variáveis analíticas do dataset processado"
)
| Variável | Tipo | Descrição | Faixa / Categorias |
|---|---|---|---|
| data_hora | POSIXct | Timestamp do intervalo de 15 minutos | 01/01 a 31/01/2025 |
| local_equipamento | character | Código do equipamento de monitoramento | 37 equipamentos únicos |
| volume_veiculos | integer | Total de veículos no intervalo (soma das 11 faixas) | 1 a 475 (mediana: 63) |
| velocidade_media | double | Velocidade média ponderada pelos pontos médios das faixas (km/h) | 5 a 85.5 km/h (média: 40.2) |
| hora | integer | Hora do dia extraída de data_hora (0–23) | 0 a 23 |
| dia_semana | factor (7 níveis) | Dia da semana em português (Segunda a Domingo) | Segunda, Terça, Quarta, Quinta, Sexta, Sábado, Domingo |
| tipo_dia | factor (2 níveis) | Classificação do dia: Dia Útil ou Final de Semana | 209,652 registros úteis / 74,345 FdS |
A primeira análise investiga como o volume de veículos se distribui ao longo do dia, identificando horários de pico e calmaria.
resumo_hora <- dados %>%
group_by(hora) %>%
summarise(
volume_medio = mean(volume_veiculos),
volume_total = sum(volume_veiculos),
n_registros = n(),
.groups = "drop"
)
p1 <- resumo_hora %>%
ggplot(aes(
x = hora,
y = volume_medio,
text = paste0(
"<b>", sprintf("%02d:00", hora), "</b>",
"<br>Volume médio: ", round(volume_medio, 1), " veículos",
"<br>Registros: ", n_registros
)
)) +
geom_area(fill = "#2196F3", alpha = 0.18) +
geom_line(color = "#1565C0", linewidth = 1.3) +
geom_point(size = 2.8, shape = 21,
fill = "#42A5F5", color = "#0D47A1", stroke = 1.2) +
# Destaque visual dos horários de pico
annotate("rect", xmin = 6.5, xmax = 9.5, ymin = -Inf, ymax = Inf,
fill = "#FF7043", alpha = 0.10) +
annotate("rect", xmin = 16.5, xmax = 19.5, ymin = -Inf, ymax = Inf,
fill = "#FF7043", alpha = 0.10) +
scale_x_continuous(
breaks = 0:23,
labels = sprintf("%02d:00", 0:23),
expand = expansion(add = 0.5)
) +
scale_y_continuous(
labels = scales::comma,
expand = expansion(mult = c(0, 0.08))
) +
labs(
title = "Volume Médio de Veículos por Hora do Dia — Janeiro 2025",
subtitle = "Regiões sombreadas em laranja indicam os horários de pico (7h–9h e 17h–19h)",
x = "Hora do Dia",
y = "Volume Médio de Veículos",
caption = "Fonte: Portal de Dados Abertos da Prefeitura do Recife"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40", size = 10),
plot.caption = element_text(color = "gray55", size = 8),
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
panel.grid.minor = element_blank()
)
ggplotly(p1, tooltip = "text") %>%
layout(
hovermode = "x unified",
xaxis = list(title = "Hora do Dia"),
yaxis = list(title = "Volume Médio de Veículos")
)
Insight: O gráfico revela a clássica curva bimodal do tráfego urbano. O pico matutino concentra-se entre 7h e 9h, período que coincide com o deslocamento casa–trabalho/escola, atingindo os maiores volumes do dia. O pico vespertino, ocorrendo entre 17h e 19h, reflete o retorno dos trabalhadores e apresenta intensidade ligeiramente superior. A madrugada (0h–5h) registra volumes mínimos — queda de mais de 90% em relação ao pico —, configurando a janela ideal para obras e manutenção viária. Para a CTTU, esses dados fundamentam a programação de ciclos semafóricos adaptativos e o escalonamento de agentes de tráfego nos momentos críticos.
A segunda análise identifica os pontos de monitoramento (radares) que registram o maior fluxo acumulado de veículos no mês de janeiro.
top10_locais <- dados %>%
group_by(local_equipamento) %>%
summarise(
volume_total = sum(volume_veiculos),
vel_media_local = round(mean(velocidade_media), 1),
n_registros = n(),
.groups = "drop"
) %>%
slice_max(order_by = volume_total, n = 10) %>%
mutate(
# Remove o sufixo "- Radar XX" para rótulos mais limpos no eixo
local_curto = str_remove(local_equipamento, " - Radar.*$")
)
p2 <- top10_locais %>%
ggplot(aes(
x = reorder(local_curto, volume_total),
y = volume_total,
fill = volume_total,
text = paste0(
"<b>", local_equipamento, "</b>",
"<br>Volume total: ", scales::comma(volume_total),
" veículos",
"<br>Velocidade média: ", vel_media_local, " km/h",
"<br>Registros no período: ", n_registros
)
)) +
geom_col(width = 0.72, show.legend = FALSE) +
scale_fill_gradient(low = "#81D4FA", high = "#01579B") +
scale_y_continuous(
labels = scales::comma,
expand = expansion(mult = c(0, 0.12))
) +
coord_flip() +
labs(
title = "Top 10 Pontos de Monitoramento por Volume Total de Tráfego",
subtitle = "Radares com maior registro acumulado de veículos — Janeiro de 2025",
x = NULL,
y = "Volume Total de Veículos",
caption = "Fonte: Portal de Dados Abertos da Prefeitura do Recife"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40", size = 10),
plot.caption = element_text(color = "gray55", size = 8),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank()
)
ggplotly(p2, tooltip = "text") %>%
layout(
xaxis = list(title = "Volume Total de Veículos"),
yaxis = list(title = "")
)
Insight: A análise revela uma concentração expressiva do tráfego em poucas vias estruturantes. As avenidas no topo do ranking são corredores de importância metropolitana, conectando bairros residenciais ao centro e ao sistema viário de maior fluxo. Essa concentração tem uma implicação estratégica clara: intervenções de engenharia de tráfego ou fiscalização eletrônica nesses pontos críticos têm efeito multiplicador sobre a mobilidade geral da cidade. Gestores podem, portanto, priorizar investimentos em monitoramento, sinalização inteligente e manutenção da via pública justamente nos locais identificados.
A terceira análise compara hora a hora o comportamento do fluxo de veículos entre dias úteis e finais de semana, explorando o efeito das férias escolares de janeiro na mobilidade urbana.
resumo_tipo_dia <- dados %>%
group_by(hora, tipo_dia) %>%
summarise(
volume_medio = mean(volume_veiculos),
n_registros = n(),
.groups = "drop"
)
p3 <- resumo_tipo_dia %>%
ggplot(aes(
x = hora,
y = volume_medio,
color = tipo_dia,
fill = tipo_dia,
group = tipo_dia,
text = paste0(
"<b>", tipo_dia, "</b>",
"<br>Hora: ", sprintf("%02d:00", hora),
"<br>Volume médio: ", round(volume_medio, 1), " veículos",
"<br>Registros: ", n_registros
)
)) +
geom_area(alpha = 0.13, position = "identity") +
geom_line(linewidth = 1.3) +
geom_point(size = 2.6, shape = 21, color = "white", stroke = 1.2) +
scale_color_manual(
values = c("Dia Útil" = "#1565C0", "Final de Semana" = "#C62828"),
name = "Tipo de Dia"
) +
scale_fill_manual(
values = c("Dia Útil" = "#1565C0", "Final de Semana" = "#C62828"),
name = "Tipo de Dia"
) +
scale_x_continuous(
breaks = 0:23,
labels = sprintf("%02d:00", 0:23),
expand = expansion(add = 0.5)
) +
scale_y_continuous(
labels = scales::comma,
expand = expansion(mult = c(0, 0.08))
) +
labs(
title = "Volume Médio de Veículos por Hora: Dias Úteis × Finais de Semana",
subtitle = "Comportamento do tráfego em janeiro de 2025 (período de férias escolares)",
x = "Hora do Dia",
y = "Volume Médio de Veículos",
caption = "Fonte: Portal de Dados Abertos da Prefeitura do Recife"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40", size = 10),
plot.caption = element_text(color = "gray55", size = 8),
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
legend.position = "top",
legend.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
ggplotly(p3, tooltip = "text") %>%
layout(
hovermode = "x unified",
legend = list(
orientation = "h", y = 1.12,
x = 0.5, xanchor = "center"
)
)
Insight: O contraste entre os dois perfis ilustra claramente o efeito das férias escolares sobre a mobilidade de Recife. Nos dias úteis, o padrão bimodal se mantém marcado, com picos matutino e vespertino bem definidos, evidenciando que o tráfego comercial e de serviços essenciais sustenta a circulação mesmo sem o fluxo escolar. Nos finais de semana, o volume é consideravelmente menor e mais distribuído ao longo do dia, com um único pico deslocado para o meio do dia, refletindo o caráter recreativo dos deslocamentos. Essa diferença reforça a necessidade de regimes operacionais distintos de fiscalização e sinalização para cada tipo de dia, mesmo em períodos atípicos como as férias de verão.
A tabela abaixo complementa o gráfico anterior com valores numéricos precisos, facilitando comparações hora a hora entre os dois tipos de dia. A coluna Variação (%) indica quanto o volume em dias úteis supera (ou não) o volume nos finais de semana — valores positivos (azul) indicam maior tráfego em dias úteis; negativos (vermelho) indicam o inverso.
tabela_comp <- dados %>%
group_by(hora, tipo_dia) %>%
summarise(volume_medio = round(mean(volume_veiculos), 1), .groups = "drop") %>%
pivot_wider(names_from = tipo_dia, values_from = volume_medio) %>%
arrange(hora) %>%
mutate(
Hora = sprintf("%02d:00", hora),
`Variação (%)` = round((`Dia Útil` - `Final de Semana`) / `Final de Semana` * 100, 1)
) %>%
select(Hora, `Dia Útil`, `Final de Semana`, `Variação (%)`)
DT::datatable(
tabela_comp,
caption = "Tabela 3 — Volume médio de veículos por hora: Dias Úteis × Finais de Semana",
rownames = FALSE,
options = list(
pageLength = 24,
scrollX = TRUE,
dom = "t",
language = list(info = "")
)
) %>%
DT::formatStyle(
"Variação (%)",
color = DT::styleInterval(0, c("#C62828", "#1565C0")),
fontWeight = "bold"
) %>%
DT::formatStyle(
c("Dia Útil", "Final de Semana"),
background = DT::styleColorBar(range(c(tabela_comp$`Dia Útil`,
tabela_comp$`Final de Semana`)),
"#E3F2FD")
)
Este relatório investigou os padrões de mobilidade urbana em Recife a
partir dos registros de monitoramento eletrônico de velocidade coletados
em janeiro de 2025. A análise seguiu um pipeline estruturado: importação
e limpeza dos dados, engenharia de atributos temporais
(hora, dia_semana, tipo_dia) e
análise exploratória orientada por três perguntas de negócio concretas,
todas apresentadas por meio de visualizações interativas geradas com
ggplot2 e plotly.
| # | Análise | Principal Descoberta |
|---|---|---|
| 1 | Padrões Temporais | Dois picos de tráfego bem definidos: 7h–9h (matutino) e 17h–19h (vespertino), com queda superior a 90% na madrugada (0h–5h). |
| 2 | Índice por Região | O tráfego é altamente concentrado em poucas vias estruturantes; as 10 vias do ranking respondem pela maior parcela do volume total da cidade. |
| 3 | Dinâmica de Janeiro | Dias úteis mantêm o perfil bimodal mesmo em período de férias; finais de semana apresentam fluxo reduzido com pico único e tardio. |
Para ampliar o valor analítico deste trabalho, recomenda-se: (i) estender a análise para os demais meses de 2025 e comparar sazonalidades; (ii) incorporar variáveis externas como condições meteorológicas e eventos especiais (Carnaval, feriados regionais); e (iii) explorar modelos preditivos de machine learning para antecipação de congestionamentos e apoio à tomada de decisão em tempo real.
Relatório produzido com R Markdown · Dados: Portal de Dados Abertos da Prefeitura do Recife · Autor: Luis Abreu · Publicado no RPubs