SISTEMA DE MONITORAMENTO DE CRIMINALIDADE - BPTran

Período analisado: r format(min(df\(data), "%m/%Y") a r format(max(df\)data), "%m/%Y") (24 meses completos)

Fonte: SEJUSP/MG | Extração: r format(Sys.Date(), "%d/%m/%Y")

Visão Geral

Row

Total de Ocorrências

60131

Furtos

50924

Roubos

9207

% de Roubos (Violência)

15.3%

Row

Estatística Descritiva Mensal por RPM

Tendência Mensal: Roubos vs Furtos

Gráficos Detalhados

Row

Gráfico 1: Proporção (Furto x Roubo)

Gráfico 2: Top 15 Municípios

Row

Gráfico 3: RMBH vs Interior (por Natureza)

Gráfico 4: Distribuição por RPM

Mapas Temáticos

Row

Mapa 1: Mancha Criminal por Município (MG)

Mapa 2: Volume por RPM (dissolvido)

---
title: "Monitoramento de Criminalidade (Veículos)"
author: "Lehônidas Santos Souza"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: scroll
    theme: cosmo
    source_code: embed
---

```{r setup_principal, include=FALSE}
library(flexdashboard)
library(tidyverse)
library(janitor)
library(DT)
library(plotly)
library(sf)
library(geobr)
library(lubridate)

# Configurações globais de chunks
knitr::opts_chunk$set(
  echo = FALSE,
  warning = FALSE,
  message = FALSE
)

# 1) CORES / IDENTIDADE
cor_navbar <- "#2C3E50"
cor_furto  <- "#2980B9"
cor_roubo  <- "#C0392B"
cor_na     <- "#EBEDEF"

# Função de limpeza de texto (robusta p/ latin1)
limpar_texto <- function(x) {
  x %>%
    as.character() %>%
    iconv(from = "", to = "UTF-8") %>%
    stringr::str_squish() %>%
    toupper()
}

# 2) CARREGAMENTO E TRATAMENTO
# Certifique-se de que os arquivos estão na mesma pasta
f_raw <- read.csv2("furtados.csv", encoding = "latin1", check.names = FALSE)
r_raw <- read.csv2("roubados.csv", encoding = "latin1", check.names = FALSE)

df_bruto <- bind_rows(f_raw, r_raw) %>%
  rename(
    registros     = 1,
    natureza      = 2,
    municipio_raw = 4,
    cod_ibge      = 5,
    mes_raw       = 6,
    ano_raw       = 7,
    risp_raw      = 8,
    rmbh_raw      = 9
  ) %>%
  mutate(
    municipio = limpar_texto(municipio_raw),
    natureza  = case_when(
      str_detect(toupper(natureza), "FURTO") ~ "FURTO",
      str_detect(toupper(natureza), "ROUBO") ~ "ROUBO",
      TRUE ~ toupper(natureza)
    ),
    # Extrai o número e monta "Xª RPM"
    rpm  = str_replace(limpar_texto(risp_raw), "RISP (\\d+).*", "\\1ª RPM"),
    rmbh = limpar_texto(rmbh_raw),
    mes  = as.integer(mes_raw),
    ano  = as.integer(ano_raw),
    data = make_date(ano, mes, 1),
    registros = suppressWarnings(as.numeric(registros))
  ) %>%
  filter(!is.na(data), !is.na(registros)) %>%
  mutate(cod_ibge = suppressWarnings(as.numeric(cod_ibge)))

# 3) FILTRO ÚLTIMOS 24 MESES
data_max <- max(df_bruto$data, na.rm = TRUE)
data_ini <- floor_date(data_max %m-% months(23), "month")
df <- df_bruto %>% filter(data >= data_ini & data <= data_max)

# 4) AGREGAÇÕES / KPIs
df_muni <- df %>%
  group_by(cod_ibge) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop")

df_rpm_stats <- df %>%
  group_by(rpm) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop")

stats <- df %>%
  group_by(rpm, data) %>%
  summarise(total_mes = sum(registros, na.rm = TRUE), .groups = "drop_last") %>%
  summarise(
    Media = round(mean(total_mes), 1),
    Mediana = median(total_mes),
    Desvio_Padrao = round(sd(total_mes), 1),
    Minimo = min(total_mes),
    Maximo = max(total_mes),
    Total = sum(total_mes),
    .groups = "drop"
  )

total_geral <- sum(df$registros, na.rm = TRUE)
total_furto <- sum(df$registros[df$natureza == "FURTO"], na.rm = TRUE)
total_roubo <- sum(df$registros[df$natureza == "ROUBO"], na.rm = TRUE)
p_roubo <- ifelse(total_geral > 0, round((total_roubo / total_geral) * 100, 1), 0)
```
<style> .navbar { background-color: #2C3E50 !important; } .navbar-brand { color: white !important; font-family: Arial; font-weight: bold; } body { font-family: Arial; font-size: 12px; padding-top: 8px; } .identificacao { background-color: #FDFEFE; padding: 15px; border-left: 6px solid #2C3E50; margin: 10px; border-radius: 6px; } img.logo-pm{ position: fixed; top: 8px; right: 10px; width: 55px; z-index: 9999; } </style>

<img src="bptran.png" class="logo-pm" />

<div class="identificacao"> <h3><b>SISTEMA DE MONITORAMENTO DE CRIMINALIDADE - BPTran</b></h3> <b>Período analisado:</b> r format(min(df$data), &quot;%m/%Y&quot;) a r format(max(df$data), &quot;%m/%Y&quot;) (24 meses completos)


<b>Fonte:</b> SEJUSP/MG | <b>Extração:</b> r format(Sys.Date(), &quot;%d/%m/%Y&quot;) </div>

# Visão Geral {data-icon="fa-tachometer-alt"}
## Row {data-height=150}
### Total de Ocorrências
```{r}
valueBox(total_geral, icon = "fa-car", color = "primary")
```

### Furtos
```{r}
valueBox(total_furto, icon = "fa-unlock", color = "info")
```

### Roubos
```{r}
valueBox(total_roubo, icon = "fa-exclamation-triangle", color = "danger")
```

### % de Roubos (Violência)
```{r}
valueBox(paste0(p_roubo, "%"), icon = "fa-hand-paper", color = "warning")
```

## Row {data-height=420}
### Estatística Descritiva Mensal por RPM
```{r}
datatable(stats, extensions = "Buttons", 
          options = list(dom = "Bfrtip", buttons = c("copy", "csv", "excel", "pdf"), pageLength = 10))
```

### Tendência Mensal: Roubos vs Furtos
```{r}
g_linha <- df %>%
  group_by(data, natureza) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop") %>%
  ggplot(aes(x = data, y = total, color = natureza)) +
  geom_line(linewidth = 1) +
  geom_point(size = 1.5) +
  scale_color_manual(values = c("FURTO" = cor_furto, "ROUBO" = cor_roubo)) +
  theme_minimal() +
  labs(x = NULL, y = "Ocorrências")

ggplotly(g_linha)
```

# Gráficos Detalhados {data-icon="fa-chart-bar"}
## Row
### Gráfico 1: Proporção (Furto x Roubo)
```{r}
df %>%
  group_by(natureza) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop") %>%
  plot_ly(labels = ~natureza, values = ~total, type = "pie",
          marker = list(colors = c(cor_furto, cor_roubo))) %>%
  layout(showlegend = TRUE)
```


### Gráfico 2: Top 15 Municípios
```{r}
g_top <- df %>%
  group_by(municipio) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop") %>%
  slice_max(total, n = 15) %>%
  ggplot(aes(x = reorder(municipio, total), y = total)) +
  geom_col(fill = cor_navbar) +
  coord_flip() +
  theme_minimal() +
  labs(x = NULL, y = "Ocorrências")

ggplotly(g_top)
```


## Row
### Gráfico 3: RMBH vs Interior (por Natureza)
```{r}
g_rmbh <- df %>%
  group_by(rmbh, natureza) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop") %>%
  ggplot(aes(x = rmbh, y = total, fill = natureza)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("FURTO" = cor_furto, "ROUBO" = cor_roubo)) +
  theme_minimal() +
  labs(x = "RMBH?", y = "Ocorrências")

ggplotly(g_rmbh)
```


### Gráfico 4: Distribuição por RPM
```{r}
g_rpm <- df %>%
  group_by(rpm) %>%
  summarise(total = sum(registros, na.rm = TRUE), .groups = "drop") %>%
  ggplot(aes(x = reorder(rpm, total), y = total)) +
  geom_col(fill = cor_furto) +
  coord_flip() +
  theme_minimal() +
  labs(x = NULL, y = "Ocorrências")

ggplotly(g_rpm)
```


# Mapas Temáticos {data-icon="fa-map-marked-alt"}
```{r}

# Malha municipal MG (sf)
mg_geo <- read_municipality(code_muni = "MG", year = 2020, showProgress = FALSE) %>%
  mutate(code_muni = as.numeric(substr(code_muni, 1, 6)))

# Mapa 1: municípios
mapa_muni_data <- mg_geo %>%
  left_join(df_muni, by = c("code_muni" = "cod_ibge")) %>%
  mutate(total = replace_na(total, 0))

# Mapa 2: dissolver por RPM
mapa_rpm_data <- mg_geo %>%
  left_join(df %>% select(cod_ibge, rpm) %>% distinct(), by = c("code_muni" = "cod_ibge")) %>%
  filter(!is.na(rpm)) %>%
  group_by(rpm) %>%
  summarise(.groups = "drop") %>% 
  left_join(df_rpm_stats, by = "rpm") %>%
  mutate(total = replace_na(total, 0))
```

## Row
### Mapa 1: Mancha Criminal por Município (MG)
```{r}
m1 <- ggplot(mapa_muni_data) +
  geom_sf(aes(fill = total, text = paste("Município:", name_muni, "<br>Total:", total)), color = NA) +
  scale_fill_viridis_c(na.value = cor_na, name = "Crimes") +
  theme_void()

ggplotly(m1, tooltip = "text")
```


### Mapa 2: Volume por RPM (dissolvido)
```{r}
m2 <- ggplot(mapa_rpm_data) +
  geom_sf(aes(fill = total, text = paste("RPM:", rpm, "<br>Total:", total)), color = "white", linewidth = 0.2) +
  scale_fill_distiller(palette = "YlOrRd", direction = 1, name = "Volume") +
  theme_void()

ggplotly(m2, tooltip = "text")
```