rmapshaperEl Instituto Nacional de Estadística, Geografía e Informática (INEGI)
tiene puestos a disposición del público los shapefiles con los distintos
niveles de información geográfica. Estos archivos digitales se
encuentran disponibles en el Marco Geoestadístico Nacional (MGN),
el cual es un sistema único y se presenta la división del territorio
nacional en diferentes niveles de desagregación para referir
geográficamente la información estadística de los censos y encuestas. Se
integra al Sistema Nacional de Información Estadística y Geográfica
(SNIEG).
Se cargan las bases de datos del índice de marginación a nivel
estatal para los años 2010, 2015 y
2020. Las cuales se encuentran en formato
.RData.
Bases de datos
- Nivel estatal
- Nivel municipal
- Nivel localidad
- Nivel AGEB
- Nivel Colonia
Base de datos de los tres años se encuentran disponibles en la página oficial de CONAPO
Datos abiertos de México datos.gob.mx
Publicación Índice De Marginación Por Entidad Federativa Y Municipio 2020
A continuación, se leen y se transforman los shapefiles de las
divisiones geográficas de los estados de México correspondientes a los
años 2020, 2015 y 2010.
Utilizando la paquetería rgdal, se definen los
siguientes parámetros:
readOGR: Esta función se usa para leer
shapefiles.dsn: Especifica la ruta al directorio que contiene el
shapefile.layer: Especifica el nombre de la capa dentro del
shapefile.encoding: Especifica la codificación de los caracteres,
en este caso, UTF-8.use_iconv: Se usa para convertir la codificación si es
necesario.Una vez cargados los sahpefiles, se transforman los sistemas de coordenadas:
spTransform: Esta función se usa para transformar las
coordenadas del shapefile a un nuevo sistema de referencia.CRSobj: Especifica el sistema de referencia de
coordenadas de destino. En este caso, se usa el sistema de coordenadas
geográficas (latitud y longitud) basado en el elipsoide y
datum WGS84.Estos pasos son cruciales para asegurar que los datos geoespaciales sean consistentes y compatibles para su uso en análisis geográficos y visualización, por ejemplo, en aplicaciones de Leaflet o cualquier otro software de mapeo.
Shapefile estados 2020
shape_estados_2020 <- readOGR(dsn = "D:/MGN/MGN 2020/MGN 2020/conjunto_de_datos",
layer = "00ent",
encoding = "UTF-8",
use_iconv = TRUE)
shape_estados_2020 <- spTransform(shape_estados_2020, CRSobj = CRS('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'))Shapefile estados 2015
shape_estados_2015 <- readOGR(dsn ="D:/MGN/MGN Junio 2016/conjunto_de_datos",
layer = "areas_geoestadisticas_estatales",
encoding = "UTF-8",
use_iconv = TRUE)
shape_estados_2015 <- spTransform(shape_estados_2015, CRSobj = CRS('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'))Shapefile estados 2010
shape_estados_2010 <- readOGR(dsn ="D:/MGN/MGN 2010 Version 4.3 (Jul-Dic 2009)/32_Entidades_Federativas",
layer = "ESTADOS",
encoding = "UTF-8",
use_iconv = TRUE)
shape_estados_2010 <- spTransform(shape_estados_2010, CRSobj = CRS('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'))Se cambian de IDs de los Features del Shapefile; de esta
manera si se hace alguna manipulación al shapefile directamente los
polígonos tendrán el ID de la clave de la entidad y conservarán el
orden. Además de que es útil cuando se necesita asegurar que los IDs de
las entidades geográficas sean consistentes en longitud y formato para
su posterior análisis o visualización.
sp::spChFIDs cambia los IDs de las features del objeto
Spatial.str_pad(shape_estados_2020@data$CVE_ENT, 2, "left", pad = "0"):
Utiliza la función str_pad() para rellenar con ceros a la
izquierda (si es necesario) para asegurarse de que cada ID tenga al
menos 2 dígitos.shape_estados_2020 <- shape_estados_2020 %>%
select(CVE_ENT) %>%
sp::spChFIDs(., str_pad(shape_estados_2020@data$CVE_ENT, 2, "left", pad = "0"))
shape_estados_2015 <- shape_estados_2015 %>%
select(CVE_ENT) %>%
sp::spChFIDs(., str_pad(shape_estados_2015@data$CVE_ENT, 2, "left", pad = "0"))
shape_estados_2010 <- shape_estados_2010 %>%
select(CVE_ENT) %>%
sp::spChFIDs(., str_pad(shape_estados_2010@data$CVE_ENT, 2, "left", pad = "0"))Se insertan los datos del índice de marginación y se seccionan por grado de marginación
Este código realiza las siguientes acciones:
CVE_ENT y GM_ del
dataframe DP2_.stringr::str_trim(.$GM_, "both"): Elimina los espacios
en blanco al principio y al final de los valores en
GM_.fct_relevel(..., c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")):
Reordena los niveles del factor GM_ en el orden
especificado.spdplyr:::left_join.Spatial(), Realiza un merge entre
shape_estados_ y el dataframe modificado, usando CVE_ENT
como clave.El resultado es un nuevo objeto Spatial (capa_estados_2020) que
combina la geometría de shape_estados_2020 con la información adicional
de DP2_, incluyendo la columna GM_ con niveles
reordenados.
capa_estados_2020 <- shape_estados_2020 %>%
spdplyr:::left_join.Spatial(., DP2_2020 %>%
select(CVE_ENT, GM_2020) %>%
mutate(GM_2020 = fct_relevel(stringr::str_trim(.$GM_2020, "both"), c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo"))),
by = c("CVE_ENT"))
capa_estados_2015 <- shape_estados_2015 %>%
spdplyr:::left_join.Spatial(., DP2_2015 %>%
select(CVE_ENT, GM_2015) %>%
mutate(GM_2015 = fct_relevel(stringr::str_trim(.$GM_2015, "both"), c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo"))),
by = c("CVE_ENT"))
capa_estados_2010 <- shape_estados_2010 %>%
spdplyr:::left_join.Spatial(., DP2_2010 %>%
select(CVE_ENT, GM_2010) %>%
mutate(GM_2010 = fct_relevel(stringr::str_trim(.$GM_2010, "both"), c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo"))),
by = c("CVE_ENT")) Se crean listas de capas de polígonos filtrados por los grados de
marginación para los años 2020, 2015 y
2010.
- Las listas (layers_estados_2020,
layers_estados_2015, layers_estados_2010),
cada una con cinco elementos. Cada elemento es una capa de polígonos
filtrada por un grado de marginación específico.
grados <- c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")
layers_estados_2020 <- list()
layers_estados_2015 <- list()
layers_estados_2010 <- list()
for(i in 1:5){
layers_estados_2020[[i]] <- capa_estados_2020 %>%
filter(GM_2020 == grados[i])
layers_estados_2015[[i]] <- capa_estados_2015 %>%
filter(GM_2015 == grados[i])
layers_estados_2010[[i]] <- capa_estados_2010 %>%
filter(GM_2010 == grados[i])
}geojson_json() (Por grados de marginación)Se convierten las capas de polígonos filtrados en objetos
GeoJSON. Este proceso es útil para guardar las capas en un
formato que puede ser fácilmente utilizado para visualización en la web
o en aplicaciones de mapas interactivos.
geojsonio::geojson_json: Esta función convierte un
objeto espacial a formato GeoJSON.geometry = "polygon": Especifica que las geometrías
deben ser de tipo polígono. Esto es adecuado para las entidades
geográficas de los estados que generalmente se representan como
polígonos.geojsonio::geojson_write: Esta función escribe un
objeto GeoJSON a un archivo.Esto es útil para guardar y compartir datos espaciales en un formato ampliamente compatible, como GeoJSON, que puede ser fácilmente utilizado en aplicaciones web, sistemas de información geográfica (SIG), y otros contextos de análisis y visualización de datos geoespaciales.
capa_estados_2020_json <- list()
capa_estados_2015_json <- list()
capa_estados_2010_json <- list()
for(i in 1:5){
capa_estados_2020_json[[i]] <- geojsonio::geojson_json(layers_estados_2020[[i]], geometry = "polygon")
capa_estados_2015_json[[i]] <- geojsonio::geojson_json(layers_estados_2015[[i]], geometry = "polygon")
capa_estados_2010_json[[i]] <- geojsonio::geojson_json(layers_estados_2010[[i]], geometry = "polygon")
}La función ms_simplify del paquete
rmapshaper sirve para simplificar las geometrías de los
polígonos en tres conjuntos de datos:
capa_estados_2020_json, capa_estados_2015_json
y capa_estados_2010_json. La simplificación se hace con el
objetivo de reducir la cantidad de puntos que definen las geometrías,
manteniendo una representación aproximada de las mismas y mejorando el
rendimiento del mapa, ya que las geometrías simplificadas requieren
menos recursos computacionales y tiempo para ser dibujadas.
La función ms_simplify(), es muy útil para simplificar
geometrías, pero encontrar un equilibrio entre la simplificación y la
preservación de la forma original de los polígonos puede requerir
ajustes cuidadosos de los parámetros. Aquí tienes algunas
recomendaciones y opciones de parámetros que puedes ajustar:
keep: controla la proporción de puntos originales que
se mantienen. Un valor más alto mantendrá más detalles y un valor más
bajo reducirá más puntos.keep_shapes = TRUE.weighting: controla cómo se ponderan los puntos en la
simplificación. Un valor positivo hará que los puntos con mayor densidad
sean menos simplificados. Ejemplo, weighting = 1.snap = TRUE: puede usarse para evitar que los puntos de
los polígonos se desvíen demasiado lejos de su posición original.capa_estados_2020_mapshaper <- list()
capa_estados_2015_mapshaper <- list()
capa_estados_2010_mapshaper <- list()
for(i in 1:5){
capa_estados_2020_mapshaper[[i]] <- rmapshaper::ms_simplify(capa_estados_2020_json[[i]], keep = 0.5, weighting = 0.9, keep_shapes = TRUE, snap = TRUE)
capa_estados_2015_mapshaper[[i]] <- rmapshaper::ms_simplify(capa_estados_2015_json[[i]], keep = 0.5, weighting = 0.9, keep_shapes = TRUE, snap = TRUE)
capa_estados_2010_mapshaper[[i]] <- rmapshaper::ms_simplify(capa_estados_2010_json[[i]], keep = 0.5, weighting = 0.9, keep_shapes = TRUE, snap = TRUE)
}⚖️ Comparativo de tamaños
geojson_write()La funcióngeojson_write del paquete
geojsonio para escribir archivos GeoJSON a
partir de los datos en las listas. Este código permitirá generar
múltiples archivos GeoJSON, uno para cada combinación de año
(2020, 2015, 2010) y dentro cada
grado de marginación.
for(i in 1:5){
geojsonio::geojson_write(capa_estados_2020_json[[i]], file = paste0(here::here(), "/Output/estados_2020_", i, "_json.geojson"))
geojsonio::geojson_write(capa_estados_2015_json[[i]], file = paste0(here::here(), "/Output/estados_2015_", i, "_json.geojson"))
geojsonio::geojson_write(capa_estados_2010_json[[i]], file = paste0(here::here(), "/Output/estados_2010_", i, "_json.geojson"))
}👇 Se vuelve a leer un archivo GeoJSON y realizan
algunas operaciones adicionales en el objeto espacial resultante:
geojsonio::geojson_read(): Esta función lee un archivo
GeoJSON y lo convierte en un objeto espacial.what = "sp": Especifica que el resultado debe ser un
objeto Spatial (de la clase sp) y no un formato lineal
.json.sp::spChFIDs: Esta función cambia los IDs de las
features (FIDs) del objeto Spatial.grados <- c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")
shape_estados_2020 <- list()
shape_estados_2015 <- list()
shape_estados_2010 <- list()
for (i in 1:5){
shape_estados_2020[[paste0(grados[i])]] <- geojsonio::geojson_read(paste0(here::here(), "/Output/estados_2020_", i, "_json.geojson"), what = "sp") %>%
sp::spChFIDs(., str_pad(.@data$CVE_ENT, 2, "left", pad = "0"))
shape_estados_2015[[paste0(grados[i])]] <- geojsonio::geojson_read(paste0(here::here(), "/Output/estados_2015_", i, "_json.geojson"), what = "sp") %>%
sp::spChFIDs(., str_pad(.@data$CVE_ENT, 2, "left", pad = "0"))
shape_estados_2010[[paste0(grados[i])]] <- geojsonio::geojson_read(paste0(here::here(), "/Output/estados_2010_", i, "_json.geojson"), what = "sp") %>%
sp::spChFIDs(., str_pad(.@data$CVE_ENT, 2, "left", pad = "0"))
}
shape_estados <- geojsonio::geojson_read(paste0(here::here(), "/Output/estados_2020_json.geojson"), what = "sp") %>%
sp::spChFIDs(., str_pad(.@data$CVE_ENT, 2, "left", pad = "0"))Se crea una paleta de colores que se usará para mapear valores de una variable categórica a colores en una visualización de Leaflet.
paleta <- c("#13322B", #Muy alto
"#086953", #Alto
"#4C9562", #Medio
"#D1BB9E", #Bajo
"#C3BA6D") # Muy bajo
## Paleta de colores
mypalette <- leaflet::colorFactor(palette = paleta,
domain = forcats::fct_relevel(DP2_2020$GM_2020, c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")),
na.color = "transparent")Se define el estilo y el contenido de un título para un mapa Leaflet
utilizando HTML y CSS dentro de
R.
tags$style(HTML("...")): Esta función permite incluir
estilos CSS en el documento..leaflet-control.map-title: Define una clase CSS que se
aplicará al título del mapa.tags$div(...): Crea un contenedor div en el cual se
coloca el título del mapa.tag.map.title: Aplica los estilos definidos
anteriormente a este contenedor div.# Estructura del título
tag.map.title <- tags$style(HTML("
.leaflet-control.map-title {
transform: translate(-50%,20%);
position: fixed !important;
left: 50%;
text-align: center;
padding-left: 10px;
padding-right: 10px;
background: rgba(255,255,255,0.75);
font-weight: bold;
font-size: 28px;
}
"))
# Nota de página
title <- tags$div(
tag.map.title, HTML("Fuentes:Estimaciones del CONAPO con base en el INEGI, Censo de Población y Vivienda 2020.")
) Se calcula el cuadro delimitador que contiene las coordenadas de los
límitesde un objeto espacial utilizando la función
st_bbox() de la librería sf.
xmin: La coordenada mínima en el eje x (longitud
mínima).ymin: La coordenada mínima en el eje y (latitud
mínima).xmax: La coordenada máxima en el eje x (longitud
máxima).ymax: La coordenada máxima en el eje y (latitud
máxima).## xmin ymin xmax ymax
## -118 15 -87 33
years: Un vector que contiene los años para los que
tenemos datos de shapefiles.grados: Un vector que contiene los niveles de
marginación.Se asigna a la lista shape_estados con una estrcutura de
listas de data frames geoespaciales correspondientes a diferentes años y
grados de marginación. Para cada data frame de los
SpatiaPolygonsDataFrame, se le añaden varias columnas
nuevas: una con IDs únicos, otra con el año correspondiente, otra con
una combinación de ID y año.
Vector y función
- years: Se define un vector con los años
2020, 2015 y 2010.
- generate_ids: Es una función que genera una secuencia de
números que los convierte en caracteres y les agrega ceros a la
izquierda para que tengan al menos dos dígitos. -
map2(shape_estados, years, ...): La función en conjunto
transforma los shapefiles de cada año y grado, generando IDs únicos y
añadiendo columnas adicionales que ayudan a identificar cada observación
con un ID y un año específicos.
Se generan algunas variables que van a ayudar a integrar los años y los grados de marginación dentro del leaflet de manera dinámica.
ID: Se genera IDs únicos para cada entidad, utilizando
la función generate_ids. Por ejemplo, para el primer año
(2020), generará IDs del 1 al 32; para el segundo año (2015), del 33 al
64; y para el tercer año (2010), del 65 al 96. Tomando en cuenta que
cada año, se encuentra estructurado por un grupo de listas que
corresponden a los diferentes grados de marginación.ANIO: Agrega una columna con el año correspondiente
(2020, 2015 o 2010).id_year: Crea una columna que combina el ID generado
con el año correspondiente, por ejemplo, 0102020, 0202020, etc.# Define los grados y años
years <- c("2020", "2015", "2010")
grados <- c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")
shape_estados <- NULL
shape_estados <- list(shape_estados_2020, shape_estados_2015, shape_estados_2010)
# Función para generar el ID del 1 a 96
generate_ids <- function(start, end) {
str_pad(as.character(seq(start, end)), 2, "left", pad = "0")
}
# Aplicar la transformación a cada lista de shape_estados
start_id <- 1
shape_estados <- map2(shape_estados, years, function(shape_files, year) {
shape_files <- map2(shape_files, grados, function(shape_file, grado) {
if (is.data.frame(shape_file@data)) {
end_id <- start_id + nrow(shape_file) - 1
shape_file <- shape_file %>%
mutate(ID = generate_ids(start_id, end_id),
ANIO = year,
id_year = paste0(generate_ids(start_id, end_id), year))
start_id <<- end_id + 1
}
shape_file
}
)
shape_files
}
)Se define una función llamada addPolygonLayer, la cual
añade una capa de polígonos a un mapa de Leaflet. Se tienen que
especificar los argumentos:
map: El objeto de mapa de Leaflet al que se le añadirá
la nueva capa de polígonos.data: Los datos que contienen la información geográfica
de los polígonos.year: Año asociado con los datos de los polígonos,
usado para agrupar.paleta: Paleta de colores que se usará para rellenar
los polígonos de acuerdo al grado de marginación.grado: Representa el grupo al que pertenecen estos
polígonos.id: Es el identificador único para esta capa de
polígonos en el mapa. Puede ser útil para identificar y manipular
específicamente esta capa en operaciones posteriores.# Define una función para añadir capas de polígonos
addPolygonLayer <- function(map, data, year, grado, paleta, id) {
map <- map %>%
addPolygons(data = data,
fillColor = paleta,
fillOpacity = 0.8,
stroke = TRUE,
weight = 1,
dashArray = "1",
opacity = 1.3,
color = "#DBDBDB", # line colour
highlight = highlightOptions(weight = 2,
color = "red", # Color de selección
dashArray = "",
fillOpacity = 0.6,
bringToFront = TRUE),
group = grado,
layerId = id
)
return(map)
}Se crea un mapa centrado en unas coordenadas específicas
(lat = 23.6260333 y lng = -102.5375005), con
un nivel de zoom fijo, y establece los límites máximos para evitar que
el usuario se desplace fuera de una región definida. El mapa utiliza
capa de OpenStreetMap tanto en la capa base como en una capa adicional
de tiles del mismo proveedor.
# Crear el mapa inicial
map <- leaflet(options = leafletOptions(minZoom = 5, maxZoom = 5, zoomControl = FALSE)) %>%
addTiles() %>%
setView(lat = 23.6260333, lng = -102.5375005, zoom = 5) %>%
setMaxBounds(lng1 = bounding_box[1],
lat1 = bounding_box[2],
lng2 = bounding_box[3],
lat2 = bounding_box[4]) %>%
addProviderTiles(providers$OpenStreetMap, options = providerTileOptions(minZoom = 5, maxZoom = 5))addPolygonLayer()Se añaden las capas de polígonos al mapa de Leaflet para cada
combinación de año y grado. Se recorren todas las combinaciones posibles
de años (years) y grados (grados), y para cada
combinación, añade una capa de polígonos al mapa utilizando la función
addPolygonLayer. La lista shape_estados contiene los datos
geográficos organizados por año y grado, y la lista paleta proporciona
la paleta de colores correspondiente para cada grado.
addPolygonLayer()Se construye dinámicamente un mapa interactivo que muestra diferentes
capas de polígonos para los años 2020, 2015 y
2010, utilizando funciones y enfoques que permiten manejar
de manera flexible los datos geoespaciales. Cada iteración del bucle
añade una nueva capa de polígonos al mapa map, lo que
permite visualizar los datos geoespaciales para cada año de manera
superpuesta en el mismo mapa interactivo. Se recorren todas las
combinaciones posibles de años (years), y se añade una capa
de polígonos al mapa utilizando la función addPolygonLayer.
La función contiene, los shape_estados que son los datos geográficos
organizados por año y grado, la paleta de colores correspondiente para
cada grado y el ID unico de cada observación correspondiente a cada
año.
# Define los datos y años
years <- c("2020", "2015", "2010")
grados <- c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo")
# Añadir capas de polígonos para cada año
for (i in seq_along(years)) {
for(j in seq_along(grados)){
map <- addPolygonLayer(map,
data = shape_estados[[i]][[j]],
year = ~ANIO,
grado = ~get(paste0("GM_", years[i])),
paleta = ~mypalette(get(paste0("GM_", years[i]))),
id = ~id_year
)
}
}Se añaden los controles adicionales y una leyenda al mapa de Leaflet. Permitiendo al usuario explorar diferentes capas de datos y visualizar información geoespacial de manera organizada y comprensible.
addLayersControl(): Agrega un control de capas al mapa
para permitir al usuario seleccionar qué capas base u overlay
(superpuestas) desea visualizar.overlayGroups = c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo"):
Define los grupos de capas superpuestas que se mostrarán en el control
de capas. En este caso, parecen ser categorías de grado de
marginación.baseGroups = c("2020", "2015", "2010"): Define los
grupos de capas base que se mostrarán en el control de capas. Estos
podrían ser los años para los cuales se están visualizando datos.options = layersControlOptions(collapsed = FALSE):
Especifica las opciones del control de capas. collapsed = FALSE
significa que el control de capas estará expandido por defecto,
mostrando todas las opciones disponibles sin necesidad de expandirlo
manualmente.map <- map %>%
addControl(title, position = "bottomright") %>%
addLegend("bottomright",
colors = paleta,
labels = grados,
title = stringr::str_wrap("Grado de marginación", 15),
opacity = 0.7) %>%
addLayersControl(
overlayGroups = c("Muy alto", "Alto", "Medio", "Bajo", "Muy bajo"),
baseGroups = c("2020", "2015", "2010"),
options = layersControlOptions(collapsed = FALSE))El bloque de este código JavaScript se utiliza junto con el paquete
htmlwidgets para controlar la visibilidad y la
interactividad de las capas en un mapa Leaflet. Este código JavaScript
personalizado mejora la funcionalidad de un mapa Leaflet al permitir que
el usuario controle dinámicamente qué capas base y superpuestas están
visibles en el mapa. Al cambiar la capa base o añadir capas
superpuestas, las capas que no corresponden se ocultan automáticamente,
manteniendo así una visualización clara y organizada de los datos
geoespaciales.
Los eventos baselayerchange, overlayadd,
overlayremove: Añaden eventos para actualizar las capas
visibles cuando el usuario cambia la capa base o añade/remueve capas
superpuestas.
baselayerchange: Este evento se activa cuando el
usuario cambia la capa base del mapa.overlayadd: Este evento se activa cuando se añade una
capa superpuesta al mapa.map <- map %>%
htmlwidgets::onRender("
function(el, x) {
var myMap = this;
var baseLayer = '2020';
myMap.eachLayer(function(layer) {
var id = layer.options.layerId;
if (id) {
if (!id.endsWith(baseLayer)) {
layer.getElement().style.display = 'none';
}
}
});
myMap.on('baselayerchange', function(e) {
baseLayer = e.name;
myMap.eachLayer(function(layer) {
var id = layer.options.layerId;
if (id) {
if (!id.endsWith(baseLayer)) {
layer.getElement().style.display = 'none';
layer.closePopup();
}
else {
layer.getElement().style.display = 'block';
}
}
});
});
myMap.on('overlayadd', function(e) {
myMap.eachLayer(function(layer) {
var id = layer.options.layerId;
if (id) {
if (!id.endsWith(baseLayer)) {
layer.getElement().style.display = 'none';
} else {
layer.getElement().style.display = 'block';
}
}
});
});
}")
map