A lo largo de este documento se utilizará RStudio para transformar bases de datos gubernamentales en en mapas interactivos para su correcta visualización a través de 3 etapas:
Procesaremos el registro masivo de víctimas de la Fiscalía General de Justicia de la CDMX utilizando Tidyverse.
Transitaremos a la detección de “focos rojos” mediante clústeres y mapas de calor para los delitos de robo, violencia familiar y delitos sexuales.
Conectaremos nuestro código en tiempo real con la API del Directorio Estadístico Nacional de Unidades Económicas (DENUE - INEGI) para mapear la infraestructura comercial y financiera sobre imágenes satelitales.
%>%)Para Mac, el atajo de teclado es Command +
Shift + M.
Para Windows, el atajo es Control + Shift +
M.
Comenzaremos por cargar las herramientas necesarias y extraer los datos abiertos de víctimas de la Fiscalía General de Justicia de la CDMX.
# CARGA DE LIBRERÍAS
# install.packages(c("tidyverse", "leaflet", "leaflet.extras", "jsonlite"))
library(tidyverse) # Ecosistema para manipulación de datos
library(leaflet) # Creación de mapas interactivos
library(leaflet.extras) # Extensión de leaflet (por addHeatmap)
library(jsonlite) # Permite leer datos desde las APIs en formato JSON
# DESCARGA Y PREPARACIÓN DE DATOS
# read_csv lee el archivo directamente desde el portal de datos abiertos
fgj = read_csv("https://archivo.datos.cdmx.gob.mx/FGJ/victimas/victimasFGJ_2024.csv")
# Creamos una base más ligera conservando solo 3 columnas clave
fgj_corto = fgj %>%
select(delito, latitud, longitud)
# Exploramos la frecuencia de los delitos
fgj_corto %>%
count(delito, sort = TRUE) %>%
head(10)
## # A tibble: 10 × 2
## delito n
## <chr> <int>
## 1 VIOLENCIA FAMILIAR 23841
## 2 FRAUDE 13795
## 3 AMENAZAS 12711
## 4 ROBO DE ACCESORIOS DE AUTO 5694
## 5 ROBO DE OBJETOS 5228
## 6 USURPACIÓN DE IDENTIDAD 4480
## 7 ROBO DE OBJETOS DEL INTERIOR DE UN VEHICULO 3763
## 8 ROBO A TRANSEUNTE EN VIA PUBLICA CON VIOLENCIA 3667
## 9 ABUSO SEXUAL 2798
## 10 DESPOJO 2285
d1 = fgj_corto %>%
filter(delito == "ROBO A CASA HABITACION SIN VIOLENCIA") %>%
filter(!is.na(latitud)) %>%
filter(!is.na(longitud))
Utilidad: Es la visualización más directa. Sirve para identificar la dispersión general o patrones geométricos muy evidentes como los delitos que ocurren a lo largo de una avenida. Su principal desventaja es que, ante una gran cantidad de datos, los puntos se enciman y el mapa se vuelve ilegible.
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircles(
data = d1,
lng = ~longitud,
lat = ~latitud
)
Utilidad: Resuelve el problema de la saturación visual. Agrupa los eventos cercanos en “burbujas” numéricas dinámicas. Es ideal para tableros de control directivos porque permite cuantificar rápidamente el volumen de incidentes en una zona sin perder la capacidad de hacer zoom hasta el nivel de calle.
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
data = d1,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
Utilidad: La herramienta analítica más potente. La capa de calor resalta de inmediato los “focos rojos” mediante densidad de color, guiando la atención del analista. La capa de clústeres superpuesta permite conservar el rigor cuantitativo, logrando un balance entre la intuición visual y el dato.
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addHeatmap(
data = d1,
lng = ~longitud,
lat = ~latitud,
radius = 60
) %>%
addCircleMarkers(
data = d1,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
d2 = fgj_corto %>%
filter(delito == "VIOLENCIA FAMILIAR") %>%
filter(!is.na(latitud)) %>%
filter(!is.na(longitud))
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircles(
data = d2,
lng = ~longitud,
lat = ~latitud
)
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
data = d2,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addHeatmap(
data = d2,
lng = ~longitud,
lat = ~latitud,
radius = 60
) %>%
addCircleMarkers(
data = d2,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
A diferencia de los casos anteriores, emplearemos
str_detect() para capturar todas las variantes tipológicas
que contengan la raíz de la palabra.
base_limpia <- fgj %>%
select(delito, latitud, longitud) %>%
filter(str_detect(delito, "SEX")) %>%
na.omit()
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircles(
data = base_limpia,
lng = ~longitud,
lat = ~latitud
)
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
data = base_limpia,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addHeatmap(
data = base_limpia,
lng = ~longitud,
lat = ~latitud,
radius = 60
) %>%
addCircleMarkers(
data = base_limpia,
lng = ~longitud,
lat = ~latitud,
clusterOptions = markerClusterOptions()
)
Las políticas de prevención requieren cruzar datos de seguridad con el entorno económico. Para obtener el censo de negocios en tiempo real, conectaremos R directamente con los servidores del INEGI mediante su API.
¿Cómo funciona el servidor del INEGI?
La instrucción se envía a través de una URL estructurada de la siguiente manera:
Base: .../Buscar/ Le indica al
sistema que haremos una consulta de texto.
Palabra clave: bancos El giro
comercial que nos interesa.
Coordenadas:
19.4408544561198,-99.20399200125259 Ubicación mediante
latitud y longitud, en este caso, el Museo Soumaya.
Radio: 500 Metros a la redonda
desde la ubicación.
Token: 5782893c... Nuestra llave de
acceso a la base de datos.
Utilidad del mapa satelital: Proyectar estos datos
sobre una imagen de satélite (Esri.WorldImagery) nos
permite verificar la infraestructura urbana real como avenidas y parques
que rodea a estas unidades económicas.
# 1. Ejecutamos la petición a la API del INEGI para obtener los bancos alrededor del Museo Soumaya en un radio de 500 metros
soumaya <- fromJSON("https://www.inegi.org.mx/app/api/denue/v1/consulta/Buscar/bancos/19.4408544561198,-99.20399200125259/500/5782893c-bfe7-42da-8ee4-02d141d52797")
# 2. Conversión a formato numérico
soumaya$Longitud <- as.numeric(soumaya$Longitud)
soumaya$Latitud <- as.numeric(soumaya$Latitud)
# 3. Mapeo satelital de los bancos encontrados
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery) %>%
addCircles(
data = soumaya,
lng = ~Longitud,
lat = ~Latitud,
color = "red",
label = ~paste(Nombre, "-", Clase_actividad)
)
Modifica la URL de la función fromJSON() en la sección
anterior con las siguientes rutas para visualizar otras ubicaciones en
la República Mexicana:
Estadio BBVA en Monterrey: Busca alrededor de las coordenadas:
25.669295827488895, -100.24388500476128.
Farmacias alrededor del Ángel de la Independencia con un radio de
750 metros:
https://www.inegi.org.mx/app/api/denue/v1/consulta/Buscar/farmacia/19.427141997797538,-99.16727748910374/750/5782893c-bfe7-42da-8ee4-02d141d52797
Restaurantes alrededor de la Pirámide de Chichén Itzá con un
radio de 1000 metros:
https://www.inegi.org.mx/app/api/denue/v1/consulta/Buscar/restaurante/20.68319666510934,-88.56821995095045/1000/5782893c-bfe7-42da-8ee4-02d141d52797