Is there a function to crop sf map object, similar to maptools::pruneMap(lines, xlim= c(4, 10), ylim= c(10, 15))
used for SpatialPolygon or SpatialLine?
I am considering st_intersection()
but there can be proper way.
Since today, there is a st_crop
function in the github version of sf
(devtools::install_github("r-spatial/sf")
, probably on CRAN in the near future too).
Just issue:
st_crop(nc, c(xmin=-82, xmax=-80, ymin=35, ymax=36))
The vector must be named with xmin xmax ymin ymax
(in whichever order).
You can also use any object that can be read by st_bbox
as cropping limits, which is very handy.
st_intersection
is probably the best way. Find whatever way works best to get an sf
object to intersect with your input. Here's a way using the convenience of raster::extent
and a mix of old and new. nc
is created by example(st_read)
:
st_intersection(nc, st_set_crs(st_as_sf(as(raster::extent(-82, -80, 35, 36), "SpatialPolygons")), st_crs(nc)))
I don't think you can coax st_intersection
to not need an exact matching CRS, so either set both of them to NA or make sure they are the same. There's no easy tools for bbox/extent afaik, so using raster is good way to make things easy-ish.
st_intersection
but couldn't solve it myself.
spex::spex
to replace the st_as_sf(as(...))
call. Also, tmaptools::crop_shape()
can do this.
Another workaround, for me it was faster for larger shapefiles:
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)
st_intersection()
approach was user: 1.18, system: 0.05, elapsed 1.23 on your dataset. (Probably my environment is different with yours... not sure.)
@mdsumner's solution as a function. Works if rasta
is a RasterBrick, extent, 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)))
}
It throws away the crs information of the raster because I don't know how to convert a raster crs() into an st_crs()
On my machine and for my data sample this has equivalent performance to raster::crop
with a SpatialLinesDataFrame version of the data.
@pbaylis's solution is about 2.5 times slower:
# Slower option.
crop.sf2 = function(sfdf, rasta) {
st_as_sf(crop(as(sfdf, "Spatial"), rasta))
}
Edit: Somebodies comment suggests spex, which produces SpatialPolygons with the crs from the rasta, if it has a crs.
This code uses the same method as 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))
}
st_crop
function which is probably worth checking out.