Introducción

El paquete sf de R se diseñó para facilitar el trabajo con el estándar «Simple Features» (sf) para la representación de datos vectoriales geográficos dentro del ecosistema de R. El paquete sf se lanzó por primera vez en 2016 y, en pocos años, había superado con creces al paquete sp (lanzado por primera vez en 2005) como la representación de datos geográficos más utilizada para datos vectoriales en R. Además de ofrecer compatibilidad con el estándar de datos «simple features», sf incluye una amplia gama de funciones para trabajar con datos vectoriales espaciales en R. Si estás acostumbrado a trabajar con datos espaciales utilizando software tradicional de SIG de escritorio, como QGIS o ArCGIS, encontrarás en el paquete sf, potenciado por los paquetes de tidyverse, equivalentes a las herramientas típicas de SIG para el análisis, la consulta, la selección, el geoprocesamiento y la visualización.

De la página web de Simple Features para R

«Simple Features» (sf) o «Simple Feature Access» hace referencia a un estándar formal (ISO 19125-1:2004) que describe cómo se pueden representar en los ordenadores los objetos del mundo real, haciendo hincapié en la geometría espacial de dichos objetos. También describe cómo se pueden almacenar y recuperar dichos objetos de las bases de datos, y qué operaciones geométricas deben definirse para ellos. La norma está ampliamente implementada en bases de datos espaciales (como PostGIS), SIG comerciales (p. ej., ESRI ArcGIS) y constituye la base de datos vectoriales para bibliotecas como GDAL.

Objetivos del cuaderno

Este cuaderno te servirá de introducción al paquete sf y al trabajo con datos vectoriales geográficos según el estándar de datos «Simple Features» (sf). Este cuaderno solo pretende ser una introducción muy breve al paquete sf, ya que aquí no se tratarán muchas otras funciones de sf.

✨ Requisitos previos ✨

Disponer de una copia del archivo shapefile MGN2023_MPIO_POLITICO, disponible en DANE (y utilizado desde el inicio del curso de Geomática Básica).

Descripción general del cuaderno

  • Configuración

  • Lectura y escritura de datos espaciales

  • Creación y visualización de objetos espaciales

1. Configuración

Este cuaderno debe estar ubicado en tu directorio GB2, cerca del directorio donde hayas guardado tus datos.

Este cuaderno requiere los siguientes paquetes y funciones de R.

Puedes instalar las bibliotecas necesarias desde la consola utilizando install.packages(«nombre_de_la_biblioteca»). Si la instalación se realiza correctamente, deberás cargar sf y dplyr para utilizar sus funciones:

library(sf)  
## Linking to GEOS 3.14.1, GDAL 3.12.1, PROJ 9.7.1; sf_use_s2() is TRUE
library(dplyr) 
## 
## Adjuntando el paquete: '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)   # Graficación avanzada
library(ggspatial) # Escala gráfica y flecha de norte

2. Lectura y escritura de datos espaciales

2a. Lectura de datos espaciales con st_read

La función st_read del paquete sf lee datos vectoriales espaciales desde diversos formatos compatibles con GDAL (Geospatial Data Abstraction Library), entre los que se incluyen ESRI Shapefile (.shp), GeoJSON (.geojson), GeoPackage (.gpkg), KML (.kml) y KMZ (.kmz), CSV con WKT (texto bien conocido) (.csv) y otros.

st_read simplifica el proceso de lectura de datos espaciales al reconocer automáticamente el formato del archivo y devolver los datos como un objeto de características simples (sf).

#Get the filenames close to your notebook
list.files(".//datos")
##  [1] "Depto_Guajira.gpkg"  "Guaj_munic.gpkg"     "Guajira"            
##  [4] "Guajira.dbf"         "Guajira.gpkg"        "Guajira.prj"        
##  [7] "Guajira.qmd"         "Guajira.shp"         "Guajira.shx"        
## [10] "Guajira_final.gpkg"  "Guajira_nueva.gpkg"  "Guajira11111.gpkg"  
## [13] "Guajira2.gpkg"       "Guajirann.gpkg"      "imagen 1.png"       
## [16] "imagen 2.png"        "Mun_Guajira.gpkg"    "municipios.gpkg"    
## [19] "Municipios2025.gpkg" "worldcities.csv"

Ahora puedes especificar la ruta relativa para leer el archivo Shapefile:

# leer el archivo shapefile *Municipios* como un objeto sf

Guajira <- st_read(".//datos//Guajira.shp")
## Reading layer `Guajira' from data source 
##   `C:\Users\nicol\OneDrive - Universidad Nacional de Colombia\2026-2\geomatica\Carpeta poryectos GB\Proyecto 7\Datos\Guajira.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 15 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -73.66494 ymin: 10.39676 xmax: -71.11296 ymax: 12.45944
## Geodetic CRS:  WGS 84

Cuando utilizamos st_read para leer un archivo Shapefile, obtenemos una vista previa de algunos de los metadatos espaciales del archivo.

  • Los datos se han leído mediante el controlador ESRI Shapefile.

  • Los datos incluyen 1121 elementos (el número de municipios de Colombia) y tienen 11 campos de atributos.

  • El tipo de geometría es multipolígono. ¿Qué es un multipolígono?

  • El rectángulo delimitador es: ………… ¡Completa esta información!

  • El sistema de referencia de coordenadas (SRC) es MAGNA-SIRGAS. Consulta tu cuaderno de física para conocer los parámetros de este SRC.

head(Guajira)

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.

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

★ Consejo profesional:

El parámetro append = F permite que el archivo sobrescriba un archivo ya existente con el mismo nombre en el directorio de trabajo.

st_write(Guajira, "Guajira2b.geojson", driver = "GeoJSON", append = F)
## Deleting layer not supported by driver `GeoJSON'
## Deleting layer `Guajira2b' failed
## Writing layer `Guajira2b' to data source `Guajira2b.geojson' using driver `GeoJSON'
## Updating existing layer Guajira2b
## Writing 15 features with 6 fields and geometry type Multi Polygon.
list.files(pattern="geojson")
## [1] "Guajira.geojson"   "Guajira2b.geojson"
Guajira2 <- st_read("./Guajira.geojson")
## Reading layer `Guajira' from data source 
##   `C:\Users\nicol\OneDrive - Universidad Nacional de Colombia\2026-2\geomatica\Carpeta poryectos GB\Proyecto 7\Guajira.geojson' 
##   using driver `GeoJSON'
## Simple feature collection with 15 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -73.66494 ymin: 10.39676 xmax: -71.11296 ymax: 12.45944
## Geodetic CRS:  WGS 84

2c. Tipos de datos espaciales compatibles con las funciones st_read y st_write

#3. Selección de elementos geográficos

3.1 Selección por atributos

La herramienta «Seleccionar por atributos» del software SIG nos permite introducir una expresión de consulta SQL para seleccionar los elementos geográficos que cumplan con los criterios de selección.

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

#(Guajira <- dplyr::filter(Guajira, NAME_1 =="La Guajira")) NO ES NECESARIO PORQUE LOS DATOS YA ESTAN FILTRADOS

Revisa el número de características seleccionadas. ¿Coincide con la información que tenías anteriormente sobre tu departamento?

Entonces, hagamos un mapa muy básico de los municipios de Santander:

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

Tenga en cuenta que trazamos los límites de los municipios, así como sus centroides.

Ahora, podemos guardar los elementos seleccionados en un nuevo archivo Geopackage para usarlos más adelante:

##st_write( Guajira,"./datos/Guajirann.gpkg",layer = "Guajira",driver = "GPKG", append = FALSE)

5.2 Seleccionar por ubicación

Una operación muy común al trabajar con datos geográficos es el proceso de seleccionar elementos en función de una relación espacial con otro objeto (capa). En el software SIG, este proceso suele realizarse mediante la herramienta «Seleccionar por ubicación». Esta herramienta permite seleccionar elementos basándose en las siguientes relaciones:

  • intersección: Se seleccionarán los elementos de la capa de entrada si se cruzan con un elemento de selección. Esta es la opción predeterminada.

  • dentro_de_una_distancia: Se seleccionarán los elementos de la capa de entrada si se encuentran dentro de la distancia especificada (utilizando la distancia euclidiana) de un elemento de selección. Usa el parámetro distancia_de_búsqueda para especificar la distancia.

  • contiene: Se seleccionarán los elementos de la capa de entrada si contienen un elemento de selección.

  • contiene_completamente: Se seleccionarán los elementos de la capa de entrada si contienen completamente un elemento de selección.

  • within: Se seleccionarán los elementos de la capa de entrada si se encuentran dentro de un elemento de selección.

  • completely_within: Se seleccionarán los elementos de la capa de entrada si se encuentran completamente dentro de un elemento de selección o están contenidos por él.

  • are_identical_to: Se seleccionarán los elementos de la capa de entrada si son idénticos (en geometría) a un elemento de selección.

  • toca_el_límite: Se seleccionarán los elementos de la capa de entrada si tienen un límite que toca un elemento de selección. Cuando los elementos de entrada son líneas o polígonos, el límite del elemento de entrada solo puede tocar el límite del elemento de selección, y ninguna parte del elemento de entrada puede cruzar el límite del elemento de selección.

  • comparten_un_segmento_de_línea_con: Se seleccionarán los elementos de la capa de entrada si comparten un segmento de línea con un elemento de selección. Tanto los elementos de entrada como los de selección deben ser líneas o polígonos.

  • cruzados_por_el_contorno_de: Se seleccionarán los elementos de la capa de entrada si son cruzados por el contorno de un elemento de selección. Tanto los elementos de entrada como los 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 contorno (línea) del polígono. Se seleccionarán las líneas que se crucen en un punto; no se seleccionarán las líneas que compartan un segmento de línea.

  • have_their_center_in: Se seleccionarán los elementos de la capa de entrada si su centro se encuentra dentro de un elemento 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 entradas de línea, se utiliza el punto medio de la geometría.

Ilustremos la funcionalidad de selección por ubicación.

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

cities = read.csv('.//datos//worldcities.csv') %>% 
         st_as_sf(coords=c("lng","lat"), crs=4326) # remember x=longitude and y=latitude

¿Qué son las ciudades?

cities

Quizás hayamos notado que el CRS de los dos conjuntos de datos (es decir, «santander» y «cities») no coinciden. Demostremos esto:

st_crs(cities)$epsg
## [1] 4326
st_crs(Guajira)$epsg
## [1] 4326

Antes de utilizar cualquier selección por ubicación, debemos transformar el SCR de las ciudades para que coincida con el SCR de Santander. Podemos hacerlo utilizando la función st_transform:

# take note of this function sintax
ncities <- st_transform(cities, crs= st_crs(Guajira))

Ahora ya estamos listos para empezar:

Guaj_cities <- ncities[Guajira, , op = st_within]

¿Obtuvimos lo que esperábamos?

Verifiquémoslo nuevamente con un gráfico sencillo:

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

Observa la variedad de símbolos que se pueden utilizar para representar geometrías puntuales:

4. Creación de gráficos con elegancia

4.1 Creación de gráficos con ggplot

Usaremos ggplot() y llamaremos a geom_sf(), lo cual le indica a R que estamos trabajando con datos espaciales. Al crear un mapa, también es fundamental considerar el orden de nuestras capas. Si colocamos nuestros datos de ciudades (stder_cities) antes del polígono de los municipios de Santander (santander), las ciudades quedarán debajo del polígono de los municipios y no podremos verlas.

ggplot() +
  #Add  municipalities
  geom_sf(data = Guajira) +
  #Add cities layer
  geom_sf(data = Guaj_cities, aes(color = city, label = city), size = 3) +
  #Add titles
  labs(x = "Longitud", y = "Latitud", title = "Ciudades de Santander") +
  #Add theme
  theme_bw()
## Warning in layer_sf(geom = GeomSf, data = data, mapping = mapping, stat = stat,
## : Ignoring unknown aesthetics: label

## 4.2 Creación de gráficos con ggplot y ggspatial

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

ggplot() +
  
  #Recortar los límites de Virginia a la extensión espacial de las ciudades y agregar la capa de Virginia
  geom_sf(data = Guajira) +
  
  #Agregar capa de ciudades
  geom_sf(data = Guaj_cities, aes(color = city, label = city), size = 3) +
  
  #Agregar una barra de escala en la esquina inferior izquierda desde ggspatial
  annotation_scale(location = "tl", height = unit(.25, "cm"), 
                   width = unit(1, "cm"), pad_x = unit(0.3, "in"), 
                   pad_y = unit(0.5, "in")) +
  
  #Agregar una flecha de norte en la esquina inferior izquierda desde ggspatial
  annotation_north_arrow(height = unit(1, "cm"), width = unit(1, "cm"),
                         which_north = "true", location = "tl", 
                         pad_x = unit(0.5, "in"), pad_y = unit(0.05, "in")) +
  
  #Agregar títulos
  labs(x = "Longitud", y = "Latitud", title = "Ciudades de Santander") +
  
  #Agregar tema
  theme_bw()
## Warning in layer_sf(geom = GeomSf, data = data, mapping = mapping, stat = stat,
## : Ignoring unknown aesthetics: label
## Warning in annotation_scale(location = "tl", height = unit(0.25, "cm"), :
## Ignoring unknown parameters: `width`

Si obtuviste resultados similares a los que se muestran arriba, ¡¡¡felicidades!!!

5. Entorno informático

sessionInfo()
## R version 4.6.2 (2026-10-29 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8  LC_CTYPE=Spanish_Colombia.utf8   
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C                     
## [5] LC_TIME=Spanish_Colombia.utf8    
## 
## 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.11 ggplot2_4.0.3    dplyr_1.2.1      sf_1.1-3        
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.6.2     tidyselect_1.2.1  
##  [5] Rcpp_1.1.2         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.13          knitr_1.52         tibble_3.3.1       units_1.0-1       
## [17] DBI_1.3.0          bslib_0.12.0       pillar_1.11.1      RColorBrewer_1.1-3
## [21] rlang_1.3.0        cachem_1.1.0       xfun_0.62          sass_0.4.10       
## [25] S7_0.2.2           otel_0.2.0         cli_3.6.6          withr_3.0.3       
## [29] magrittr_2.0.5     wk_0.9.5           class_7.3-24       digest_0.6.39     
## [33] grid_4.6.2         rstudioapi_0.19.0  lifecycle_1.0.5    vctrs_0.7.3       
## [37] KernSmooth_2.23-27 proxy_0.4-29       evaluate_1.0.5     glue_1.8.1        
## [41] farver_2.1.2       e1071_1.7-17       rmarkdown_2.32     tools_4.6.2       
## [45] pkgconfig_2.0.3    htmltools_0.5.9