Configuracion inicial

Limpiamos el entorno, y cargamos las librerias que utilizaremos

# Limpiar el entorno

rm(list=ls())

# Librerias

pacman::p_load(tidyverse, 
               readxl, # Leer el excel
               rgdal, # Leer los shp de mapas
               maptools,
               stringi, # Manipular strings
               ggplot2,  # Gráficas y mapas
               viridis) # Escala de color

if (!require(gpclib)) install.packages("gpclib", type="source")
gpclibPermit()

Procedemos a establecer el directorio de trabajo, en la carpeta “in” se encontraran los datos, y en la carpeta “out” se encontraran los mapas.

dir <- "C:/xxxxx/sesion R 2" # Directorio inicial
dir_in <- paste(dir,"in",sep="/") # Entrada de datos
dir_out <- paste(dir,"out",sep="/") # Salida de archivos

Nota: Cambiar las “xxxxx” por la respectiva ruta

Creación de mapas

Cargamos los datos necesarios

edos_shp <- readOGR(paste(dir_in, "ESTADOS.shp", sep="/"),verbose = FALSE) # Coordenadas
df_crimen <- read_excel(paste(dir_in, "IDEFC.xlsx", sep="/")) # Base de datos (sin limpiar)

Manipulacion de los datos

Exploremos el dataframe

print(head(df_crimen))
## # A tibble: 6 × 19
##     Año Clave_Ent Entidad    Bien …¹ Tipo …² Subti…³ Modal…⁴ Enero Febrero Marzo
##   <dbl>     <dbl> <chr>      <chr>   <chr>   <chr>   <chr>   <dbl>   <dbl> <dbl>
## 1  2021         1 Aguascali… La vid… Homici… Homici… Con ar…     2       1     4
## 2  2021         1 Aguascali… La vid… Homici… Homici… Con ar…     1       1     1
## 3  2021         1 Aguascali… La vid… Homici… Homici… Con ot…     0       3     1
## 4  2021         1 Aguascali… La vid… Homici… Homici… No esp…     0       0     0
## 5  2021         1 Aguascali… La vid… Homici… Homici… Con ar…     0       0     0
## 6  2021         1 Aguascali… La vid… Homici… Homici… Con ar…     0       0     0
## # … with 9 more variables: Abril <dbl>, Mayo <dbl>, Junio <dbl>, Julio <dbl>,
## #   Agosto <dbl>, Septiembre <dbl>, Octubre <dbl>, Noviembre <dbl>,
## #   Diciembre <dbl>, and abbreviated variable names ¹​`Bien jurídico afectado`,
## #   ²​`Tipo de delito`, ³​`Subtipo de delito`, ⁴​Modalidad

Notemos que el dataframe tiene un problema, y es que los nombres de las columnas tienen “carácteres especiales” (espacios, acentos), los cuales pueden dificultar su manipulacion, por lo cual procedemos a “limpiar” los nombres.

names(df_crimen) <- gsub(" ", "_", colnames(df_crimen)) # Cambiamos espacios 

names(df_crimen) <- tolower(stri_trans_general(colnames(df_crimen),"Latin-ASCII")) # Eliminamos acentos

print(names(df_crimen))
##  [1] "ano"                    "clave_ent"              "entidad"               
##  [4] "bien_juridico_afectado" "tipo_de_delito"         "subtipo_de_delito"     
##  [7] "modalidad"              "enero"                  "febrero"               
## [10] "marzo"                  "abril"                  "mayo"                  
## [13] "junio"                  "julio"                  "agosto"                
## [16] "septiembre"             "octubre"                "noviembre"             
## [19] "diciembre"

Para graficar, unicamente estamos interesados en el tipo de delito “Homicidio”, en el subtipo de delitos “Homicidio culposo” y en la modalidad “En accidente de tránsito”

df_crimen_mapa <- df_crimen %>% 
  filter(tipo_de_delito == "Homicidio" & subtipo_de_delito == "Homicidio culposo" & modalidad == "En accidente de tránsito") 

Para nuestro proposito, queremos unicamente los totales anuales

df_crimen_mapa$anual <- rowSums(df_crimen_mapa[ ,c (8,19)], na.rm = TRUE )

Procedemos a realizar el merge del dataframe con el shape para crear el mapa, pero primero debemos homologar el nombre de la variable con la que haremos el merge

df_crimen_mapa <- df_crimen_mapa %>% 
  rename(id = clave_ent)

Ahora, transformamos el shape en un dataframe

df_edos_shp <- fortify(edos_shp, region = "CVE_ENT") # "Convertimos las coordenadas a df"
## Warning in proj4string(SpP): CRS object has comment, which is lost in output; in tests, see
## https://cran.r-project.org/web/packages/sp/vignettes/CRS_warnings.html
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
## definition
print(head(df_edos_shp))
##        long      lat order  hole piece id group
## 1 -102.2879 22.41649     1 FALSE     1 01  01.1
## 2 -102.2875 22.41608     2 FALSE     1 01  01.1
## 3 -102.2870 22.41613     3 FALSE     1 01  01.1
## 4 -102.2867 22.41639     4 FALSE     1 01  01.1
## 5 -102.2865 22.41666     5 FALSE     1 01  01.1
## 6 -102.2863 22.41690     6 FALSE     1 01  01.1

Notemos que la variable “id” en df_edos_shp es string y en df_crimen_mapa es un número (lo cual afecta el merge), pasemos todo a números.

df_edos_shp$id <- as.numeric(df_edos_shp$id)

Realizamos el merge

df_crimen_mapa_shp <- df_edos_shp %>%
                      left_join(df_crimen_mapa, by="id") # Pegamos el df de crimen

Creacion del mapa

Mapa con variable continua

Recordemos que similar a %>%, ggplot tiene el símbolo +.

mapa1 <- ggplot() + #
  geom_polygon(data=df_crimen_mapa_shp, # Cargamos base de datos
               aes(x = long, # Longitud (No cambiar)
                   y = lat, # Latitud (No cambiar)
                   group = group, # Variable que identifica los datos de un estado (No cambiar)
                   fill = anual)) # Variable de interés (Cambiar)
print(mapa1)

Guardamos la imagen

ggsave(paste(dir_out, "mapa1.png", sep="/"), 
       plot=mapa1, # Objeto que se guardara como imagen
       width = 16, height = 12)

Tip: guarden sus gráficas/mapas como pdf, conservaran la mejor calidad posible, esto sirve principalmente para Rmarkdown y Overleaf.

ggsave(paste(dir_out, "mapa1.pdf", sep="/"), 
       plot=mapa1, # Objeto que se guardara como imagen
       width = 16, height = 12) # Tamaño de la imagen

Procedemos a personalizar el mapa

mapa2 <- ggplot() +
  geom_polygon(data=df_crimen_mapa_shp, aes(x = long, y = lat, group = group, fill = anual)) +
  scale_fill_viridis(option="viridis") + 
  labs(y="", x="", title="Homicidios culposos", subtitle="En accidente de tránsito", caption = "Año 2021", fill = "Núm. de casos") + # Etiquetas
  theme_void() + # Eliminar el fondo gris
  coord_map()   # Rango completo del mapa

print(mapa2)

ggsave(paste(dir_out, "mapa2.pdf", sep="/"), 
         plot=mapa2, # Objeto que se guardara como imagen
         width = 16, height = 12) # Tamaño de la imagen 
mapa3 <- mapa2 +
  theme(plot.title = element_text(size=40),plot.subtitle =element_text(size=25),plot.caption = element_text(size=20)) + theme(
    legend.title = element_text(size = 25),
    legend.text = element_text(size = 25) ) # Tamaño de las letras

print(mapa3)

ggsave(paste(dir_out, "mapa3.pdf", sep="/"), 
       plot=mapa3, # Objeto que se guardara como imagen
       width = 16, height = 12) # Tamaño de la imagen

Mapa con variable categorica

Ahora, en lugar de una escala continua, pasemos a dividir los datos por cuartiles

print(summary(df_crimen_mapa_shp$anual))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    4.00   42.00   69.00   80.79  120.00  274.00
df_crimen_mapa_shp$quartile_4 <- ntile(df_crimen_mapa_shp$anual, 4) 

Podemos hacer lo mismo con una sintaxis propia de tidyverse

df_crimen_mapa_shp <- df_crimen_mapa_shp %>% mutate(quartile_4_td = ntile(anual, 4))

Procedamos a crear el mapa

mapa4 <- ggplot() +
  geom_polygon(data=df_crimen_mapa_shp, aes(x = long, y = lat, group = group, fill = factor(quartile_4)) ) +
  scale_fill_viridis(discrete = TRUE,option = "magma",
                     breaks = c(1,2,3,4),
                     labels = c("Q1", "Q2", "Q3","Q4")) + 
  labs(y="", x="", title="Homicidios culposos", subtitle="En accidente de tránsito", caption = "Año 2021", fill = "Núm. de casos") + # Etiquetas
  theme_void() + # Eliminar el fondo gris
  coord_map()  +  # Rango completo del mapa
  theme(plot.title = element_text(size=40),plot.subtitle =element_text(size=25),plot.caption = element_text(size=20))    + theme(
    legend.title = element_text(size = 25),
    legend.text = element_text(size = 25) ) 

print(mapa4)

Guardamos el archivo

ggsave(paste(dir_out, "mapa4.pdf", sep="/"), 
       plot=mapa4, # Objeto que se guardara como imagen
       width = 16, height = 12) # Tamaño de la imagen

Mapa con rangos creados manualmente

Creamos los rangos

df_crimen_mapa_shp <- df_crimen_mapa_shp %>%
  mutate(intervalo = case_when(anual > 200 ~ "+200",
                             between(anual, 100, 200) ~ "100-200", 
                             anual < 100 ~ "menos de 100"))

Creamos el mapa

mapa5 <- ggplot() +
  geom_polygon(data=df_crimen_mapa_shp, aes(x = long, y = lat, group = group, fill = factor(intervalo)) ) +
  scale_fill_viridis(discrete = TRUE,option = "magma", direction = -1) + 
  labs(y="", x="", title="Homicidios culposos", subtitle="En accidente de tránsito", caption = "Año 2021", fill = "Núm. de casos") + # Etiquetas
  theme_void() + 
  coord_map() +  
  theme(plot.title = element_text(size=40),plot.subtitle =element_text(size=25),plot.caption = element_text(size=20))    + theme(
    legend.title = element_text(size = 25),
    legend.text = element_text(size = 25) ) 

print(mapa5)

Guardamos el mapa

ggsave(paste(dir_out, "mapa5.pdf", sep="/"), 
       plot=mapa5, 
       width = 16, height = 12)