title: “📊 Relatório de Análise de Crimes de Veículos” author: “PMMG — 3º SGT CLEIDSON DANIEL PEREIRA” output: flexdashboard::flex_dashboard: orientation: columns vertical_layout: fill theme: yeti navbar: - title: “PMMG” href: “https://www.policiamilitar.mg.gov.br/” align: right logo: “https://upload.wikimedia.org/wikipedia/commons/d/d4/Bras%C3%A3o_da_Pol%C3%ADcia_Militar_de_Minas_Gerais.svg”
# Pacotes essenciais
library(flexdashboard)
library(readr)
library(dplyr)
##
## 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(lubridate)
##
## Anexando pacote: 'lubridate'
## Os seguintes objetos são mascarados por 'package:base':
##
## date, intersect, setdiff, union
library(stringi)
library(janitor)
##
## Anexando pacote: 'janitor'
## Os seguintes objetos são mascarados por 'package:stats':
##
## chisq.test, fisher.test
library(DT)
library(plotly)
## Carregando pacotes exigidos: ggplot2
##
## Anexando pacote: 'plotly'
## O seguinte objeto é mascarado por 'package:ggplot2':
##
## last_plot
## O seguinte objeto é mascarado por 'package:stats':
##
## filter
## O seguinte objeto é mascarado por 'package:graphics':
##
## layout
library(ggplot2)
library(leaflet)
library(geobr)
## Carregando namespace exigido: sf
library(scales)
##
## Anexando pacote: 'scales'
## O seguinte objeto é mascarado por 'package:readr':
##
## col_factor
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.4, PROJ 9.7.0; sf_use_s2() is TRUE
library(tidyr)
# Opções gerais para o R
options(scipen = 999) # Desabilita notação científica
# Carregar dados
furto <- read_delim(
"data/Veiculos - Furto - Jan 2015 a Out 2025.csv",
delim = ";",
locale = locale(encoding = "UTF-8"),
show_col_types = FALSE
)
roubo <- read_delim(
"data/Veiculos - Roubo - Jan 2015 a Out 2025.csv",
delim = ";",
locale = locale(encoding = "UTF-8"),
show_col_types = FALSE
)
# Renomear para nomes limpos (snake_case)
furto <- furto %>% clean_names()
roubo <- roubo %>% clean_names()
# Tratamento de codificação (mantido por segurança)
furto <- furto %>% mutate(across(where(is.character), ~stri_encode(., from = "UTF-8", to = "UTF-8")))
roubo <- roubo %>% mutate(across(where(is.character), ~stri_encode(., from = "UTF-8", to = "UTF-8")))
# Nome correto da coluna de mês após clean_names()
nome_mes <- "mes_numerico_fato"
# Ajuste FURTO
furto <- furto %>%
mutate(
ano = as.integer(ano_fato),
mes = as.integer(.data[[nome_mes]]),
data = if_else(
!is.na(data_fato),
as.Date(data_fato),
make_date(ano, mes, 1)
),
tipo = "Furto",
qtde_veiculos = as.numeric(qtde_veiculos)
)
# Ajuste ROUBO
roubo <- roubo %>%
mutate(
ano = as.integer(ano_fato),
mes = as.integer(.data[[nome_mes]]),
data = if_else(
!is.na(data_fato),
as.Date(data_fato),
make_date(ano, mes, 1)
),
tipo = "Roubo",
qtde_veiculos = as.numeric(qtde_veiculos)
)
# Unir tudo
dados <- bind_rows(furto, roubo) %>% arrange(data)
# Sumarização para KPIs
total_furto <- sum(furto$qtde_veiculos, na.rm = TRUE)
total_roubo <- sum(roubo$qtde_veiculos, na.rm = TRUE)
total_geral <- total_furto + total_roubo
# Sumarização para Tabela Regional (RPM)
dados_rpm <- dados %>%
group_by(risp) %>%
summarise(
Total_Geral = sum(qtde_veiculos, na.rm = TRUE),
Furto = sum(qtde_veiculos[tipo == "Furto"], na.rm = TRUE),
Roubo = sum(qtde_veiculos[tipo == "Roubo"], na.rm = TRUE)
) %>%
mutate(
Proporcao_Roubo = Roubo / Total_Geral,
Proporcao_Furto = Furto / Total_Geral
) %>%
arrange(desc(Total_Geral))
# Sumarização para o gráfico de Série Temporal Mensal
dados_ts <- dados %>%
mutate(data_mes = lubridate::make_date(year = ano_fato, month = mes, day = 1)) %>%
count(data_mes, tipo)
# Sumarização para os gráficos de Tipo de Veículo
furto_tipo <- furto %>%
group_by(tipo_veiculo) %>%
summarise(n = sum(qtde_veiculos, na.rm = TRUE)) %>%
arrange(desc(n)) %>%
head(10)
roubo_tipo <- roubo %>%
group_by(tipo_veiculo) %>%
summarise(n = sum(qtde_veiculos, na.rm = TRUE)) %>%
arrange(desc(n)) %>%
head(10)
# Sumarização para o gráfico de Série Anual
dados_comb_plot <- dados %>% count(ano_fato, tipo)
Visão Geral e Tendências {data-icon=“fa-chart-line”}
Indicadores Chave (KPIs) {data-width=300}
Total Geral de Ocorrências
valueBox(
format(total_geral, big.mark = ".", decimal.mark = ","),
icon = "fa-chart-pie",
color = "primary"
)
410.907
Total de Furtos
valueBox(
format(total_furto, big.mark = ".", decimal.mark = ","),
icon = "fa-mask",
color = "warning"
)
284.020
Total de Roubos
valueBox(
format(total_roubo, big.mark = ".", decimal.mark = ","),
icon = "fa-car-crash",
color = "danger"
)
126.887
Série Temporal e Comparação Anual {data-width=700}
Comparação Furto x Roubo por Ano (Gráfico 1)
p_ano <- ggplot(dados_comb_plot, aes(x = ano_fato, y = n, color = tipo)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
scale_y_continuous(labels = scales::comma) +
labs(
title = "Comparação Furto x Roubo (2015-2025)",
x = "Ano",
y = "Quantidade",
color = "Tipo de Crime"
) +
theme_minimal() +
theme(legend.position = "bottom")
# Torna o gráfico interativo
ggplotly(p_ano, tooltip = c("x", "y", "color"))
Série Temporal Mensal (Gráfico 2)
p_ts <- ggplot(dados_ts, aes(x = data_mes, y = n, color = tipo)) +
geom_line(linewidth = 0.8) +
scale_y_continuous(labels = scales::comma) +
labs(
title = "Série Temporal Mensal por Tipo de Crime",
x = "Data",
y = "Quantidade",
color = "Tipo"
) +
theme_minimal()
# Torna o gráfico interativo
ggplotly(p_ts, tooltip = c("x", "y", "color"))
Análise Regional e Detalhada {data-icon=“fa-map-marked-alt”}
Regional: Tabela e Sumarização Interativa {data-width=400}
Tabela Interativa de Ocorrências por RISP/RPM
# Tabela interativa usando DT
datatable(
dados_rpm,
caption = 'Total e Proporção de Crimes por RPM',
options = list(
dom = 'ltipr',
pageLength = 10,
language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/Portuguese-Brasil.json')
),
rownames = FALSE,
filter = 'top'
) %>%
formatCurrency(
c('Total_Geral', 'Furto', 'Roubo'),
currency = "",
digits = 0,
mark = "."
) %>%
formatPercentage(
c('Proporcao_Roubo', 'Proporcao_Furto'),
digits = 1,
mark = ","
)
Top 10 RPMs e Proporção de Roubo (Gráfico 3)
# Top 10 RPMs por Total Geral
top_10_rpm <- dados_rpm %>%
head(10) %>%
mutate(risp = as.factor(risp))
p_sum <- ggplot(top_10_rpm, aes(x = reorder(risp, Total_Geral), y = Total_Geral, fill = Proporcao_Roubo)) +
geom_col() +
geom_text(aes(label = format(Total_Geral, big.mark = ".", scientific = FALSE)), hjust = -0.1, size = 3) +
scale_y_continuous(labels = scales::comma, limits = c(0, max(top_10_rpm$Total_Geral) * 1.1)) +
labs(
title = "Top 10 RISP/RPMs por Volume de Ocorrências",
x = "Região (RISP/RPM)",
y = "Total de Ocorrências",
fill = "Proporção de Roubo"
) +
coord_flip() +
theme_minimal() +
scale_fill_gradient(low = "lightblue", high = "red", labels = scales::percent)
# Torna o gráfico interativo
ggplotly(p_sum, tooltip = c("x", "y", "fill")) %>%
config(displayModeBar = FALSE)
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' e 'decimal.mark' são ambos '.', o que pode ser confuso
Tipologia de Veículos {data-width=600}
Furtos por Tipo de Veículo (Top 10) (Gráfico 4)
p_furto_tipo <- ggplot(furto_tipo, aes(x = reorder(tipo_veiculo, n), y = n)) +
geom_col(fill = "#56B4E9", alpha = 0.8) +
coord_flip() +
scale_y_continuous(labels = scales::comma) +
labs(
title = "Top 10 Furtos por Tipo de Veículo",
x = "Tipo de Veículo",
y = "Quantidade"
) +
theme_minimal()
ggplotly(p_furto_tipo) %>%
config(displayModeBar = FALSE)
Roubos por Tipo de Veículo (Top 10) (Gráfico 5)
p_roubo_tipo <- ggplot(roubo_tipo, aes(x = reorder(tipo_veiculo, n), y = n)) +
geom_col(fill = "#D55E00", alpha = 0.8) +
coord_flip() +
scale_y_continuous(labels = scales::comma) +
labs(
title = "Top 10 Roubos por Tipo de Veículo",
x = "Tipo de Veículo",
y = "Quantidade"
) +
theme_minimal()
ggplotly(p_roubo_tipo) %>%
config(displayModeBar = FALSE)
Análise de Oportunidade (Heatmaps) {data-icon=“fa-calendar-alt”}
Heatmap de Furtos (Ano × Mês) (Gráfico 6)
# Gera a sumarização e o Heatmap de Furtos
furto_heat <- furto %>%
count(ano_fato, mes) %>%
mutate(mes = factor(mes, levels = 1:12, labels = month.abb))
ggplot(furto_heat, aes(x = ano_fato, y = mes, fill = n)) +
geom_tile(color = "white") +
scale_fill_gradient(low = "#e5f5e0", high = "#31a354", labels = scales::comma) +
labs(
title = "Ocorrências de Furto por Mês e Ano",
x = "Ano",
y = "Mês",
fill = "Qtd"
) +
theme_minimal() +
theme(panel.grid = element_blank())
Heatmap de Roubos (Ano × Mês) (Gráfico 7)
# Gera a sumarização e o Heatmap de Roubos
roubo_heat <- roubo %>%
count(ano_fato, mes) %>%
mutate(mes = factor(mes, levels = 1:12, labels = month.abb))
ggplot(roubo_heat, aes(x = ano_fato, y = mes, fill = n)) +
geom_tile(color = "white") +
scale_fill_gradient(low = "#fee5d9", high = "#de2d26", labels = scales::comma) +
labs(
title = "Ocorrências de Roubo por Mês e Ano",
x = "Ano",
y = "Mês",
fill = "Qtd"
) +
theme_minimal() +
theme(panel.grid = element_blank())