Introducción

En este cuaderno se va a elabrorar un mapa de los municipios de la zona cafetera (Caldas, Quindío y Risaralda).

1. Configuración

Este cuaderno debe ubicarse en el directorio GB2, cerca del directorio donde guardaste tus datos.

Este cuaderno requiere los siguientes paquetes y funciones de R.

sf · Soporte para características simples, una forma estandarizada de codificar datos vectoriales espaciales. Se integra con GDAL para leer y escribir datos, con GEOS para operaciones geométricas y con PROJ para conversiones de proyección y transformaciones de datum. Utiliza por defecto el paquete s2 para operaciones de geometría esférica en coordenadas elipsoidales (longitud/latitud). Este cuaderno utiliza las siguientes funciones de sf:

st_as_sf · Convierte un objeto externo en un objeto sf.

st_bbox · Devuelve el límite de una característica simple o un conjunto de características simples.

st_geometry · Obtiene, establece, reemplaza o renombra la geometría de un objeto sf.

st_read · Lee características simples o capas desde un archivo o base de datos.

st_write · Escribe un objeto de características simples en un archivo o base de datos.

dplyr - dplyr es una gramática de manipulación de datos que proporciona un conjunto coherente de verbos para resolver los desafíos más comunes de manipulación de datos:

mutate() agrega nuevas variables que son funciones de variables existentes.

select() selecciona variables. Basándose en sus nombres.

filter() selecciona casos según sus valores.

summarise() reduce varios valores a un único resumen.

arrange() cambia el orden de las filas.

ggplot2: ggplot2 es un sistema para crear gráficos de forma declarativa, basado en la Gramática de los Gráficos. Usted proporciona los datos, le indica a ggplot2 cómo asignar variables a elementos estéticos y qué primitivas gráficas usar, y ggplot2 se encarga de los detalles.

ggspatial: los datos espaciales, junto con la potencia del framework ggplot2, facilitan la creación de mapas.

Antes de todo, hay que instalar las librerias que vasmos a utilizar.

#install.packages("sf")
#install.packages("dplyr")
#install.packages("ggplot2")
#install.packages("ggspatial")

Vamos a cargar las librerias que necesitamos

library(sf)
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(ggspatial)

2. Lectura y escritura de datos espaciales

2a. Lectura y escritura de datos espaciales con st_read

Vamos a leer datos espaciales Obtenemos el nombre nuestro archivo.

list.files("./Datos/MGN2023_MPIO_POLITICO")
## [1] "MGN_ADM_MPIO_GRAFICO.cpg"     "MGN_ADM_MPIO_GRAFICO.dbf"    
## [3] "MGN_ADM_MPIO_GRAFICO.prj"     "MGN_ADM_MPIO_GRAFICO.sbn"    
## [5] "MGN_ADM_MPIO_GRAFICO.sbx"     "MGN_ADM_MPIO_GRAFICO.shp"    
## [7] "MGN_ADM_MPIO_GRAFICO.shp.xml" "MGN_ADM_MPIO_GRAFICO.shx"

Vamos a especificar la ruta especifica para leer el shapefile

colombia <- st_read ("./Datos/MGN2023_MPIO_POLITICO/MGN_ADM_MPIO_GRAFICO.shp")
## Reading layer `MGN_ADM_MPIO_GRAFICO' from data source 
##   `/Users/felipe/Documents/GB2/Proyecto3/Datos/MGN2023_MPIO_POLITICO/MGN_ADM_MPIO_GRAFICO.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 1121 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -81.73562 ymin: -4.229406 xmax: -66.84722 ymax: 13.39473
## Geodetic CRS:  MAGNA-SIRGAS

Vamos a utilizar la función head para ver los seis primeros municipios de colombia en orden alfabetico

head(colombia)

2b. Escritura de datos espaciales con st_write

Para exportar datos espaciales, la función st_write() permite guardar un objeto sf en diversos formatos.

Puede especificar el formato de salida añadiendo la extensión de archivo correspondiente o indicando el controlador GDAL adecuado. Se pueden especificar opciones adicionales para controlar cómo se escriben los datos.

★ Consejo: El parámetro append = F permite sobrescribir un archivo existente con el mismo nombre en el directorio de trabajo.

st_write(colombia, "municipios.gpkg", driver = "GPKG", append = F)
## Deleting layer `municipios' using driver `GPKG'
## Writing layer `municipios' to data source `municipios.gpkg' using driver `GPKG'
## Writing 1121 features with 11 fields and geometry type Multi Polygon.
## eliminar la capa "municipios" utilizando el controlador "GPKG"
## escribir la capa "municipios" en la fuente de datos "municipios.gpkg" utilizando el controlador "GPKG"
## escritura de 1121 municipios con 11 categorias y tipo de geometria multipoligono
#Comprobar que se creo el nuevo archivo geopackage
list.files(pattern="gpkg")
## [1] "municipios.gpkg"         "stder_munic.gpkg"       
## [3] "zonacafetera_munic.gpkg"
# Leer el geopackage "municipios" como un obejto sf
colombia2 <- st_read("./municipios.gpkg")
## Reading layer `municipios' from data source 
##   `/Users/felipe/Documents/GB2/Proyecto3/municipios.gpkg' using driver `GPKG'
## Simple feature collection with 1121 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -81.73562 ymin: -4.229406 xmax: -66.84722 ymax: 13.39473
## Geodetic CRS:  MAGNA-SIRGAS

Selección de características

Selección por atributo

La herramienta “Seleccionar por atributo” en el software SIG permite introducir una consulta SQL para seleccionar las entidades que cumplen los criterios de selección.

Por otro lado, sf y dplyr ofrecen opciones bastante sencillas para realizar operaciones similares. Analicemos una de ellas.

(zonacafetera <- dplyr::filter(colombia, dpto_cnmbr=="QUINDIO"|dpto_cnmbr=="RISARALDA"|dpto_cnmbr=="CALDAS"))

Comprueba el número de entidades seleccionadas. ¿Coincide con la información previa sobre tu departamento?

A continuación, vamos a crear un gráfico muy básico de los municipios de la zona cafetea (Caldas, Quindío y Risaralda):

## Se trazaron los limites entre los municipios y sus centroides

plot(st_geometry(zonacafetera), col = sf.colors(12, categorical = TRUE), border = 'grey', 
     axes = TRUE)
plot(st_geometry(st_centroid(zonacafetera)), pch = 3, col = 'red', add = TRUE)
## Warning: st_centroid assumes attributes are constant over geometries

Nótese que hemos trazado los límites de los municipios, así como sus centroides.

Ahora, podemos guardar las entidades seleccionadas en un nuevo archivo geopackage para su uso posterior:

st_write(zonacafetera, "zonacafetera_munic.gpkg", driver = "GPKG", append = F)
## Deleting layer `zonacafetera_munic' using driver `GPKG'
## Writing layer `zonacafetera_munic' to data source 
##   `zonacafetera_munic.gpkg' using driver `GPKG'
## Writing 53 features with 11 fields and geometry type Multi Polygon.

Selección por localisación

Una operación muy común al trabajar con geodatos es la selección de entidades en función de su relación espacial con otro objeto (capa). En el software SIG, este proceso se suele realizar con la herramienta “Seleccionar por ubicación”. Esta herramienta permite seleccionar entidades según las siguientes relaciones:

Intersección: Las entidades de la capa de entrada se seleccionarán si intersecan una entidad de selección. Esta es la opción predeterminada.

Dentro de una distancia: Las entidades de la capa de entrada se seleccionarán si se encuentran dentro de la distancia especificada (mediante la distancia euclidiana) de una entidad de selección. Utilice el parámetro “distancia de búsqueda” para especificar la distancia.

Contiene: Las entidades de la capa de entrada se seleccionarán si contienen una entidad de selección.

Contiene completamente: Las entidades de la capa de entrada se seleccionarán si contienen completamente una entidad de selección.

Dentro de: Las entidades de la capa de entrada se seleccionarán si se encuentran dentro de una entidad de selección.

Completamente dentro: Las entidades de la capa de entrada se seleccionarán si están completamente dentro o contenidas por una entidad de selección.

are_identical_to: Las entidades de la capa de entrada se seleccionarán si son idénticas (en geometría) a una entidad de selección.

boundary_touches: Las entidades de la capa de entrada se seleccionarán si su límite toca una entidad de selección. Cuando las entidades de entrada son líneas o polígonos, el límite de la entidad de entrada solo puede tocar el límite de la entidad de selección, y ninguna parte de la entidad de entrada puede cruzar el límite de la entidad de selección.

share_a_line_segment_with: Las entidades de la capa de entrada se seleccionarán si comparten un segmento de línea con una entidad de selección. Las entidades de entrada y de selección deben ser líneas o polígonos.

crossed_by_the_outline_of: Las entidades de la capa de entrada se seleccionarán si son cruzadas por el contorno de una entidad de selección. Las entidades de entrada y de selección deben ser líneas o polígonos. Si se utilizan polígonos para la capa de entrada o de selección, se utilizará el límite (línea) del polígono. Se seleccionarán las líneas que se cruzan en un punto; las líneas que comparten un segmento de línea no se seleccionarán.

have_their_center_in: Las entidades de la capa de entrada se seleccionarán si su centro se encuentra dentro de una entidad de selección. El centro de la entidad se calcula de la siguiente manera: para polígonos y multipuntos, se utiliza el centroide de la geometría; para líneas, se utiliza el punto medio de la geometría.

Veamos cómo funciona la selección por ubicación.

Primero, leamos un archivo CSV con ciudades del mundo. Sí, es el mismo archivo que usamos hace varias semanas en este curso. ¿Recuerdas el sistema de coordenadas de referencia (CRS) de este archivo?

cities = read.csv('./Datos/worldcities/worldcities.csv') %>% st_as_sf(coords=c("lng","lat"), crs=4326)

¿Qué son las ciudades?

cities

Tenemos que comprobar que los CRS de ciudades y zonacafetra sean los mismos ya que si son diferentes no van a ser compatibles.

st_crs(cities)$epsg
## [1] 4326
st_crs(zonacafetera)$epsg
## [1] 4686

Como podemos observar los CRS de ciudades no coinciden con el CRS de zona cafetera, debemos transformar el CRS de ciudades para que coincida con el CRS de zona cafetera y eso lo realizamos con la siguiente función.

ncities <- st_transform(cities, crs= st_crs(zonacafetera))

Ahora, estamos listos para partir:

zonacafetera_cities <- ncities[zonacafetera, , op = st_within]

¿Obtuvimos lo que esperábamos?

Comprobémoslo de nuevo con un gráfico rudimentario:

plot(st_geometry(zonacafetera), col = sf.colors(12, categorical = TRUE), border = 'grey', axes = TRUE)
plot(st_geometry(zonacafetera_cities), pch = 20, col = 'red', add = TRUE)

4. Mejorando los trazos

4.1 Representación gráfica con ggplot

Usaremos ggplot y llamaremos a geom_sf() el cual le indica a R que estamos trabajando en datos espaciales. Al crear un mapa es fundamental tener en cuenta el orden de las capas Si colocamos los datos de las ciudades (zonacafetera_cities) antes del polígono de municipios de zonacafetera (zonacafetera), las ciudades quedarán debajo del polígono de municipios y no podremos verlas.

Previamente instalamos la libreria ggplot2

library(ggplot2)
ggplot() + geom_sf(data = zonacafetera) + geom_sf(data = zonacafetera_cities, aes(color = city, label = city), size = 3) + labs(x = "Longitud", y = "Latitud", title = "Ciudades de zona cafetera") + theme_bw()
## Warning in layer_sf(geom = GeomSf, data = data, mapping = mapping, stat = stat,
## : Ignoring unknown aesthetics: label

Instalamos la libreria ggspatial para mejorar los graficos de ggplot2

library(ggspatial)

4.2 Representación gráfica con ggplot y ggspatial

Ahora, añadiremos algunos elementos personalizados a nuestro mapa, como una flecha que indique el norte y una barra de escala, utilizando el paquete ggspatial de R.

ggplot() +
  #Crop Virginia boundary to spatial extent of cities and add Virginia layer
  geom_sf(data = zonacafetera) +
  #Add cities layer
  geom_sf(data = zonacafetera_cities, aes(color = city, label = city), size = 3) +
  #Add scale bar to bottom left from ggspatial
  annotation_scale(location = "tr", height = unit(.25, "cm"), 
                   width = unit(1, "cm"), pad_x = unit(0.8, "in"), 
                   pad_y = unit(2.8, "in")) +
  #Add north arrow to bottom left from ggspatial
  annotation_north_arrow(height = unit(1, "cm"), width = unit(1, "cm"),
                         which_north = "true", location = "tr", 
                         pad_x = unit(2.0, "in"), pad_y = unit(0.05, "in")) +
  #Add titles
  labs(x = "Longitud", y = "Latitud", title = "Ciudades de Zona Cafetera") +
  #Add theme
  theme_bw()
## Warning in layer_sf(geom = GeomSf, data = data, mapping = mapping, stat = stat,
## : Ignoring unknown aesthetics: label
## Warning in annotation_scale(location = "tr", height = unit(0.25, "cm"), :
## Ignoring unknown parameters: `width`

5. Entorno informático

sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS Sequoia 15.6.1
## 
## Matrix products: default
## BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: America/Bogota
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ggspatial_1.1.10 ggplot2_4.0.3    dplyr_1.2.1      sf_1.1-1        
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.5.2     tidyselect_1.2.1  
##  [5] Rcpp_1.1.1         jquerylib_0.1.4    scales_1.4.0       yaml_2.3.12       
##  [9] fastmap_1.2.0      R6_2.6.1           generics_0.1.4     classInt_0.4-11   
## [13] s2_1.1.9           knitr_1.51         tibble_3.3.1       units_1.0-1       
## [17] DBI_1.3.0          bslib_0.10.0       pillar_1.11.1      RColorBrewer_1.1-3
## [21] rlang_1.1.7        cachem_1.1.0       xfun_0.57          sass_0.4.10       
## [25] S7_0.2.1           cli_3.6.5          withr_3.0.2        magrittr_2.0.4    
## [29] wk_0.9.5           class_7.3-23       digest_0.6.39      grid_4.5.2        
## [33] rstudioapi_0.18.0  lifecycle_1.0.5    vctrs_0.7.1        KernSmooth_2.23-26
## [37] proxy_0.4-29       evaluate_1.0.5     glue_1.8.0         farver_2.1.2      
## [41] e1071_1.7-17       rmarkdown_2.31     tools_4.5.2        pkgconfig_2.0.3   
## [45] htmltools_0.5.9