Recortar objeto de características simples en R

20

¿Existe una función para recortar el objeto de mapa sf, similar a la maptools::pruneMap(lines, xlim= c(4, 10), ylim= c(10, 15))utilizada para SpatialPolygon o SpatialLine?

Estoy considerando st_intersection()pero puede haber una manera adecuada.

Kazuhito
fuente

Respuestas:

17

st_intersectionEs probablemente la mejor manera. Encuentre la forma que funcione mejor para lograr que un sfobjeto se cruce con su entrada. Aquí hay una manera de usar la comodidad raster::extenty una combinación de lo antiguo y lo nuevo. nces creado por example(st_read):

st_intersection(nc, st_set_crs(st_as_sf(as(raster::extent(-82, -80, 35, 36), "SpatialPolygons")), st_crs(nc)))

No creo que pueda convencer st_intersectionpara que no necesite un CRS que coincida exactamente, por lo tanto, establezca ambos en NA o asegúrese de que sean iguales. No hay herramientas fáciles para bbox / extensión afaik, por lo que usar raster es una buena manera de facilitar las cosas.

mdsumner
fuente
Muchas gracias @mdsumner, funcionó a las mil maravillas. Pasé horas st_intersectionpero no pude resolverlo yo mismo.
Kazuhito
Ahora puede usar spex::spexpara reemplazar la st_as_sf(as(...))llamada. Además, tmaptools::crop_shape()puede hacer esto.
AF7
1
sfahora incluye st_crop, mira mi respuesta para más detalles.
AF7
23

Desde hoy , hay una st_cropfunción en la versión de github de sf( devtools::install_github("r-spatial/sf"), probablemente en CRAN en el futuro cercano también).

Solo emite:

st_crop(nc, c(xmin=-82, xmax=-80, ymin=35, ymax=36))

El vector debe ser nombrado con xmin xmax ymin ymax(en cualquier orden).

También puede usar cualquier objeto que pueda leerse st_bboxcomo límite de recorte, lo cual es muy útil.

AF7
fuente
5

Otra solución, para mí fue más rápido para archivos de forma más grandes:

library(sf)
library(raster)
library(rgeos)
library(ggplot2)

# Load National Forest shapefile
# https://data.fs.usda.gov/geodata/edw/edw_resources/shp/S_USA.AdministrativeForest.zip
nf.poly <- st_read("S_USA.AdministrativeForest"), "S_USA.AdministrativeForest")

crop_custom <- function(poly.sf) {
  poly.sp <- as(poly.sf, "Spatial")
  poly.sp.crop <- crop(poly.sp, extent(c(-82, -80, 35, 36)))
  st_as_sf(poly.sp.crop)
}

cropped <- crop_custom(nf.poly)
pbaylis
fuente
Gracias. Es un flujo de trabajo interesante, combinación de raster :: crop () y st_as_sf () ... + 1 de mi parte. Deseo que podamos tener este tipo de función fácilmente accesible como crop () en futuras versiones de sf . En cuanto a la velocidad, una ejecución rápida de system.time con su función informó usuario: 5.42, sistema: 0.09, transcurrió 5.52 , mientras que el st_intersection()enfoque fue usuario: 1.18, sistema: 0.05, transcurrió 1.23 en su conjunto de datos. (Probablemente mi entorno es diferente al suyo ... no estoy seguro.)
Kazuhito
Eso es interesante: el enfoque st_intersection toma alrededor de 80 años para mí.
pbaylis
Tenga en cuenta que la función raster :: crop, cuando se aplica a objetos de geometría sp, actúa como un contenedor para las funciones rgeos. Aunque, un envoltorio muy conveniente. La API GEOS funciona con objetos WKT, por lo que invariablemente será un estándar para las operaciones de superposición sf.
Jeffrey Evans el
1
Y cambia con el tiempo, sf ahora tiene "indexación espacial" incorporada en 0.5-1 cran.r-project.org/web/packages/sf/news.html, por lo que probablemente ahora sea más rápido que sp / rgeos.
mdsumner
1
sfahora incluye st_crop, mira mi respuesta para más detalles.
AF7
1

La solución de @ mdsumner como función. Funciona si rastaes un RasterBrick, extensión, bbox, etc.

# Crop a Simple Features Data Frame to the extent of a raster
crop.sf = function(sfdf, rasta) {
  st_intersection(sfdf, st_set_crs(st_as_sf(as(extent(rasta), "SpatialPolygons")), st_crs(sfdf)))
}

Descarta la información crs del ráster porque no sé cómo convertir un ráster crs () en un st_crs ()

En mi máquina y para mi muestra de datos, esto tiene un rendimiento equivalente al raster::cropde una versión SpatialLinesDataFrame de los datos.

La solución de @ pbaylis es aproximadamente 2.5 veces más lenta:

# Slower option.
crop.sf2 = function(sfdf, rasta) {
  st_as_sf(crop(as(sfdf, "Spatial"), rasta))
}

Editar: el comentario de Somebodies sugiere spex , que produce SpatialPolygons con los crs del rasta, si tiene un crs.

Este código usa el mismo método que spex:

# Crop a Simple Features Data Frame to the extent of a raster
crop.sf3 <- function(sfdf, rasta) {
  # Get extent and crs
  ext.sp <- as(extent(rasta), "SpatialPolygons")
  crs(ext.sp) <- crs(rasta)

  # crop
  st_intersection(sfdf, st_as_sf(ext.sp))
}
cmc
fuente
sf ahora tiene una st_cropfunción que probablemente valga la pena revisar.
cmc