2.4 Operaciones con datos espaciales
A continuación se describe una selección de las herramientas disponibles para datos espaciales.
Para un listado completo de las funciones implementadas en el paquete sf
se puede consultar la referencia (o la “chuleta”, aunque puede contener algunos errores).
Puede que algunas herramientas (o recursos) admitan únicamente objetos Spatial*
del paquete sp
, aunque siempre se pueden emplear las funciones para convertir tipos de objetos:
st_as_sf(x, ...)
: conviertex
a un objetosf
(por ejemplo objetosSpatial*
).as(x, "Spatial")
: conviertex
a un objetoSpatial*
.
2.4.1 Importación y exportación de datos espaciales
El paquete sf
permite importar y exportar una gran cantidad de formatos de datos espaciales, almacenados en ficheros o en bases de datos, mediante las funciones st_read()
y st_write()
.
Como se mostró al principio de la Sección 2.2, estas funciones deducen el formato automáticamente a partir de la extensión del archivo (por ejemplo .shp para ESRI Shapefile) o a partir del prefijo (por ejemplo PG: para PostGIS/PostgreSQL):
<- system.file("shape", package="sf")
dir list.files(dir, pattern="^[nc]")
## [1] "nc.dbf" "nc.prj" "nc.shp" "nc.shx"
# ESRI Shapefile, consta de por lo menos de 3 ficheros, el principal .shp
<- paste0(dir, "/nc.shp")
file file
## [1] "C:/Program Files/R/R-4.1.1/library/sf/shape/nc.shp"
<- st_read(file) nc_sf
## Reading layer `nc' from data source
## `C:\Program Files\R\R-4.1.1\library\sf\shape\nc.shp' using driver `ESRI Shapefile'
## Simple feature collection with 100 features and 14 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
## Geodetic CRS: NAD27
Se admiten los formatos de datos vectoriales soportados por GDAL (que emplea internamente),
se puede obtener un listado con la función st_drivers()
:
<- st_drivers()
drivers str(drivers)
## 'data.frame': 89 obs. of 7 variables:
## $ name : chr "ESRIC" "FITS" "PCIDSK" "netCDF" ...
## $ long_name: chr "Esri Compact Cache" "Flexible Image Transport System" "PCIDSK Database File" "Network Common Data Format" ...
## $ write : logi FALSE TRUE TRUE TRUE TRUE TRUE ...
## $ copy : logi FALSE FALSE FALSE TRUE TRUE TRUE ...
## $ is_raster: logi TRUE TRUE TRUE TRUE TRUE TRUE ...
## $ is_vector: logi TRUE TRUE TRUE TRUE TRUE TRUE ...
## $ vsi : logi TRUE FALSE TRUE FALSE TRUE TRUE ...
Además, se han desarrollado una gran cantidad de paquetes de R que permiten acceder directamente desde R a datos espaciales. Muchos incluyen conjuntos de datos espaciales y otros implementan interfaces a bases de datos espaciales o geoportales disponibles en Internet. Algunos de ellos son los siguientes:
rnaturalearth
: permite importar una gran cantidad de datos vectoriales y rasterizados de Natural Earth, incluyendo datos administrativos/culturales (fronteras de países, aeropuertos, carreteras, vías férreas…) y físicos (costas, lagos…).giscoR
: permite importar datos de Eurostat - GISCO (Geographic Information System of the COmmission).mapSpain
: permite importar límites administrativos de España (CCAA, provincias, municipios…).osmdata
: permite importar “pequeños” conjuntos de datos de OpenStreetMap (OSM).osmextract
: permite importar grandes conjuntos de datos de OSM.ows4R
: (en desarrollo) proporciona una interfaz para OGC standard Web-Services (OWS).openeo
: permite importar datos de servidores openEO (Open Earth Observation data).rnoaa
: permite importar datos climáticos de la National Oceanic and Atmospheric Administration (NOAA).climaemet
: permite importar datos climáticos proporcionados por la Agencia Estatal de Meteorología de España (AEMET).meteoForecast
: permite importar resultados de los modelos numéricos de predicción meteorológica GFS, MeteoGalicia, NAM y RAP.saqgetr
: permite importar datos de calidad del aire de Europa.RGISTools
: permite importar datos de imágenes de satélite de Landsat, MODIS y Sentinel.maptools
,spData
,spDataLarge
,getlandsat
…
library(osmdata)
# Cuidado: descarga mucha información
# https://nominatim.openstreetmap.org/ui/search.html
# https://wiki.openstreetmap.org/wiki/Map_features
<- opq('A Coruña') %>%
osm_coru add_osm_feature(key = 'highway') %>%
osmdata_sf()
plot(st_geometry(osm_coru$osm_lines), main = "",
xlim = c(-8.45, -8.38), ylim = c(43.32, 43.39))
También están disponibles una gran cantidad de páginas web y geoportales desde donde es posible descargar datos espaciales (algo que se puede hacer directamente desde R). Algunas de ellas son:
CGADM database of Global Administrative Areas: permite descargar límites administrativos a distintos niveles (e.g. 0 = pais, 1 = CCAA, 2 = provincias, 3 = comarcas, 4 = ayuntamientos).
INSPIRE Geoportal: Enhancing access to European spatial data.
Copernicus Open Access Hub: Europe’s eyes on Earth.
GSHHG A Global Self-consistent, Hierarchical, High-resolution Geography Database.
Muchos de los archivos de datos están en formato NetCDF (Network Common Data Form) y se pueden importar a R con el paquete ncdf4
.
2.4.2 Operaciones con geometrías
Operaciones unarias (operan sobre un único conjunto de geometrías simples, el primer argumento) con resultado geométrico:
st_geometry()
: devuelve (o establece) la columnasfc
de un objetosf
.st_transform(x, crs, ...)
: transforma o convierte las coordenadas dex
a un nuevo sistema de referencia.st_cast(x, to, ...)
: cambia la geometríax
a otro tipo de geometría.st_centroid()
: devuelve los centroides de las geometrías.st_buffer()
: crea un buffer en torno a la geometría o a cada geometría.st_boundary()
: devuelve la frontera de la geometría.st_convex_hull()
: crea el envoltorio convexo de un conjunto de puntos.st_voronoi()
: crea una teselación de Voronoi.st_make_grid(x, cellsize, offset, n, what = c("polygons", "corners", "centers"))
: genera una rejilla rectangular (o exagonal) de geometrías (what
) que cubre los límites dex
.
Como ya se comentó en la Sección 2.2.1, nos puede interesar transformar las coordenadas a un nuevo sistema de referencia (algo necesario para poder combinar conjuntos de datos espaciales con distintos CRS). Por ejemplo podemos utilizar la proyección de Mollweide para representar datos globales (en este caso estimaciones de la población de países; Figura 2.8 derecha).
library(rnaturalearth)
<- par(mfrow = c(1, 2), mar = c(bottom = 0, left = 0, top = 0, right = 0))
par_old # NOTA: plot.sf() con escala no es compatible con mfrow
<- ne_countries(returnclass = "sf")["pop_est"]
world_pop plot(world_pop, logz = TRUE, main = "", key.pos = NULL, reset = FALSE)
<- st_graticule(crs=st_crs("WGS84"), lon = seq(-180, 180, by = 20), lat = seq(-90, 90, by = 10))
grat plot(grat[1], col = 'darkgray', add = TRUE)
# https://spatialreference.org/ref/esri/54009/
<- st_transform(world_pop, "ESRI:54009")
world_pop2 plot(world_pop2, logz = TRUE, main = "", key.pos = NULL, reset = FALSE)
<- st_graticule(world_pop2, lon = seq(-180, 180, by = 20), lat = seq(-90, 90, by = 10))
grat plot(grat[1], col = 'darkgray', add = TRUE)
par(par_old)
Operaciones binarias (operan sobre dos conjuntos de geometrías simples) con resultado geométrico:
st_union(x, y, ..., by_feature)
: une varias geometrías.st_intersection(x, y, ...)
: intersección de pares de geometrías.st_crop(x, y, ..., xmin, ymin, xmax, ymax)
: intersección con rectángulo delimitador o especificado.st_difference(x, y, ...)
: diferencia de pares de geometrías.st_sym_difference(x, y, ...)
: diferencia simétrica (xor) de pares de geometrías.st_nearest_points(x, y, ...)
: obtiene los puntos más cercanos entre pares de geometrías.
Operaciones unarias con resultado numérico o lógico:
st_coordinates(x)
: devuelve una matriz con las coordenadas.st_bbox(obj, ...)
: devuelve los límites del conjunto de geometrías.st_area(x, ...)
: devuelve el área de polígonos.st_length(x, ...)
: devuelve la longitud de líneas.st_is(x, type)
: verifica si la geometría es de un determinado tipo o conjunto de clases.
Operaciones binarias con resultado numérico o lógico:
st_distance(x, y, ..., by_element, which)
: devuelve la matriz de distancias mínimas entre geometrías.st_nearest_feature(x, y)
: devuelve el índice de la geometría dey
más cercana a cada geometría dex
.st_intersects(x, y, ...)
: determina si las geometrías se solapan o tocan.st_disjoint(x, y, ...)
: determina si las geometrías no se solapan o tocan.st_touches(x, y, ...)
: determina si las geometrías se tocan.st_overlaps(x, y, ...)
: determina si las geometrías se solapan, pero no están completamente contenidas la una en la otra.st_crosses(x, y, ...)
: determina si las geometrías se cruzan, pero no se tocan.st_within(x, y, ...)
: determina six
está eny
.st_contains(x, y, ...)
: determina siy
está enx
.st_covers(x, y, ...)
: determina si todos los puntos dey
están dentro dex
.st_covered_by(x, y, ...)
: determina si todos los puntos dex
están dentro dey
.st_equals(x, y, ...)
: determina six
es geométricamente igual ay
.st_equals_exact(x, y, par, ...)
: determina six
es igual ay
con cierta tolerancia.
El resultado de las operaciones lógicas es una matriz dispersa (de clase sgbp
, sparse geometry binary predicate), que se puede convertir a una matriz densa con as.matrix()
.
st_buffer()
) de radio 40 en torno a las posiciones de observación y a partir de él crear una rejilla vectorial (st_make_grid(..., what = "centers")
) de dimensiones 50 por 50 e intersecarla con el buffer.
load("datos/aquifer.RData")
$head <- aquifer$head/100 # en cientos de pies
aquifer<- st_as_sf(aquifer, coords = c("lon", "lat"), agr = "constant")
aquifer_sf <- aquifer_sf %>% st_geometry() %>% st_buffer(40)
buffer <- buffer %>% st_make_grid(n = c(50, 50), what = "centers") %>%
grid st_intersection(buffer)
plot(buffer)
plot(grid, pch = 3, cex = 0.5, add = TRUE)
Sin embargo, en lugar de emplear una rejilla sf
, puede resultar preferible (por ejemplo para la representación gráfica) emplear una rejilla stars
library(stars)
<- buffer %>% st_as_stars(nx = 50, ny = 50) %>% st_crop(buffer)
grid <- gstat::idw(formula = head ~ 1, locations = aquifer_sf, newdata = grid) idw
## [inverse distance weighted interpolation]
plot(idw["var1.pred"], col = sf.colors(64), main = "")
# Error gstat::idw, cambia las coordenadas del objeto stars
# summary(st_coordinates(grid))
# summary(st_coordinates(idw))
# Posible solución: añadir el resultado a `grid` y emplearlo en lugar de `idw`
# grid$var1.pred <- idw$var1.pred
# plot(grid["var1.pred"], col = sf.colors(64), axes = TRUE, main = "")