title: “Análise Criminal - 34º BPM” output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: scroll theme: flatly logo: “https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Bras%C3%A3o_da_PMMG.svg/40px-Bras%C3%A3o_da_PMMG.svg.png"# ========================================== # 1. CARREGAMENTO DE PACOTES # ========================================== library(flexdashboard) library(tidyverse) library(DT) library(geobr) library(sf) library(leaflet) library(lubridate)
df_roubo_bruto <- read.csv(“Veiculos - Roubo - Jan 2015 a Abr 2026.csv”, sep = “;”, fileEncoding = “latin1”, check.names = FALSE, stringsAsFactors = FALSE) df_hom_bruto <- read.csv(“Vítimas de Homicidio Consumado - Jan 2012 a Abr 2026.csv”, sep = “;”, fileEncoding = “latin1”, check.names = FALSE, stringsAsFactors = FALSE)
extrair_dados <- function(df, idx_muni, idx_ano, idx_mes, idx_qtd, nome_categoria) { # Isolando as colunas exatas df_reduzido <- df[, c(idx_muni, idx_ano, idx_mes, idx_qtd)] colnames(df_reduzido) <- c(“Municipio”, “Ano”, “MesNum”, “Qtd”)
df_reduzido %>% mutate( Categoria = nome_categoria, Ano = as.numeric(trimws(Ano)), MesNum = as.numeric(trimws(MesNum)), Registros = as.numeric(trimws(Qtd)) ) %>% # Filtra dados vazios e monta a data filter(!is.na(Ano) & !is.na(MesNum)) %>% mutate( Data = make_date(year = Ano, month = MesNum, day = 1) ) %>% # Filtro exato de 24 meses (Maio de 2024 a Abril de 2026) filter(Data >= as.Date(“2024-05-01”) & Data <= as.Date(“2026-04-01”)) %>% select(Municipio, Data, Categoria, Registros) }
dados_roubo <- extrair_dados(df_roubo_bruto, 22, 4, 6, 2, “Roubo de Veículos”) dados_hom <- extrair_dados(df_hom_bruto, 19, 4, 6, 2, “Homicídio Consumado”)
dados_crime <- bind_rows(dados_roubo, dados_hom) %>% replace_na(list(Registros = 0))
serie_historica <- dados_crime %>% group_by(Data, Categoria) %>% summarise(Total = sum(Registros, na.rm = TRUE), .groups = ‘drop’)
top_municipios <- dados_crime %>% group_by(Municipio, Categoria) %>% summarise(Total = sum(Registros, na.rm = TRUE), .groups = ‘drop’) %>% group_by(Municipio) %>% mutate(TotalGeral = sum(Total)) %>% ungroup() %>% arrange(desc(TotalGeral)) %>% filter(Municipio %in% unique(Municipio)[1:15]) # Filtra Top 15 para não espremer
proporcao <- dados_crime %>% group_by(Categoria) %>% summarise(Total = sum(Registros, na.rm = TRUE))
mapa_mg <- read_municipality(code_muni = “MG”, year = 2020, showProgress = FALSE)
dados_mapa <- dados_crime %>% group_by(Municipio) %>% summarise(Total_Crimes = sum(Registros, na.rm = TRUE))
mapa_crime <- mapa_mg %>% left_join(dados_mapa, by = c(“name_muni” = “Municipio”)) %>% mutate(Total_Crimes = replace_na(Total_Crimes, 0)) Visão Geral {data-icon=“fa-chart-line”}RowGráfico 1: Evolução Histórica (Últimos 24 Meses)ggplot(serie_historica, aes(x = Data, y = Total, color = Categoria, group = Categoria)) + geom_line(linewidth = 1) + geom_point(size = 3) + theme_minimal(base_size = 14) + labs(x = “Mês/Ano”, y = “Total de Registros”, title = “Roubo de Veículos vs Homicídios”) + scale_color_manual(values = c(“Roubo de Veículos” = “#f39c12”, “Homicídio Consumado” = “#c0392b”)) + theme(legend.position = “bottom”) Gráfico 2: Proporção Criminalggplot(proporcao, aes(x = ““, y = Total, fill = Categoria)) + geom_bar(stat =”identity”, width = 1) + coord_polar(“y”, start = 0) + theme_void(base_size = 14) + labs(title = “Proporção Total no Período”) + scale_fill_manual(values = c(“Roubo de Veículos” = “#f39c12”, “Homicídio Consumado” = “#c0392b”)) + theme(legend.position = “bottom”) Análise Municipal {data-icon=“fa-city”}RowGráfico 3: Municípios com Maior Incidênciaggplot(top_municipios, aes(x = reorder(Municipio, Total), y = Total, fill = Categoria)) + geom_bar(stat = “identity”, position = “dodge”) + coord_flip() + theme_minimal(base_size = 14) + labs(x = “Município”, y = “Total de Registros”, title = “Top 15 Municípios”) + scale_fill_manual(values = c(“Roubo de Veículos” = “#f39c12”, “Homicídio Consumado” = “#c0392b”)) + theme(legend.position = “bottom”, axis.text.y = element_text(size = 10)) Gráfico 4: Distribuição e Outliers (Boxplot)ggplot(dados_crime, aes(x = Categoria, y = Registros, fill = Categoria)) + geom_boxplot(alpha = 0.7) + theme_minimal(base_size = 14) + labs(x = “Categoria Criminal”, y = “Registros Mensais”, title = “Dispersão Criminal”) + scale_fill_manual(values = c(“Roubo de Veículos” = “#f39c12”, “Homicídio Consumado” = “#c0392b”)) + theme(legend.position = “none”) Tabela e Mapa {data-icon=“fa-table”}RowTabela Interativa (Dados Consolidados)datatable(dados_crime, options = list(pageLength = 10, language = list(url = ‘//cdn.datatables.net/plug-ins/1.10.11/i18n/Portuguese-Brasil.json’)), rownames = FALSE, colnames = c(“Município”, “Mês/Ano”, “Natureza”, “Total”)) Mapa Temático - Concentração de Ocorrências (Leaflet)paleta <- colorNumeric(palette = “YlOrRd”, domain = mapa_crime$Total_Crimes)
leaflet(mapa_crime) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons( fillColor = ~paleta(Total_Crimes), weight = 1, opacity = 1, color = “white”, dashArray = “3”, fillOpacity = 0.7, highlightOptions = highlightOptions( weight = 3, color = “#666”, dashArray = ““, fillOpacity = 0.9, bringToFront = TRUE), label = ~paste0(name_muni,”: “, Total_Crimes,” ocorrências”) ) %>% addLegend(pal = paleta, values = ~Total_Crimes, opacity = 0.7, title = “Total”, position = “bottomright”)