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
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)
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
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
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
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)