Recadrer un objet de fonctions simples dans R

20

Existe-t-il une fonction pour recadrer l'objet de carte sf, similaire à celle maptools::pruneMap(lines, xlim= c(4, 10), ylim= c(10, 15))utilisée pour SpatialPolygon ou SpatialLine?

J'envisage st_intersection()mais il peut y avoir moyen approprié.

Kazuhito
la source

Réponses:

17

st_intersectionest probablement le meilleur moyen. Trouvez la méthode qui convient le mieux pour qu'un sfobjet croise votre entrée. Voici une façon d'utiliser la commodité raster::extentet un mélange d'ancien et de nouveau. ncest créé par example(st_read):

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

Je ne pense pas que vous pouvez cajoler st_intersectionpour ne pas avoir besoin d'un CRS correspondant exactement, alors définissez-les tous les deux sur NA ou assurez-vous qu'ils sont les mêmes. Il n'y a pas d'outils simples pour bbox / extend afaik, donc utiliser raster est un bon moyen de simplifier les choses.

mdsumner
la source
Merci beaucoup @mdsumner, cela a fonctionné comme un charme. J'ai passé des heures st_intersectionmais je n'ai pas pu le résoudre moi-même.
Kazuhito
Vous pouvez maintenant utiliser spex::spexpour remplacer l' st_as_sf(as(...))appel. , Aussi tmaptools::crop_shape()peut le faire.
AF7
1
sfcomprend maintenant st_crop, voir ma réponse pour plus de détails.
AF7
23

Depuis aujourd'hui , il existe une st_cropfonction dans la version github de sf( devtools::install_github("r-spatial/sf"), probablement sur CRAN dans un avenir proche aussi).

Il suffit d'émettre:

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

Le vecteur doit être nommé avec xmin xmax ymin ymax(dans n'importe quel ordre).

Vous pouvez également utiliser n'importe quel objet pouvant être lu st_bboxcomme limites de recadrage, ce qui est très pratique.

AF7
la source
5

Une autre solution de contournement, pour moi, c'était plus rapide pour les fichiers de formes plus volumineux:

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
la source
Merci. C'est un workflow intéressant, combinaison de raster :: crop () et st_as_sf () ... + 1 de ma part. Je souhaite que nous puissions avoir ce genre de fonction facilement accessible comme crop () dans les futures versions de sf . En ce qui concerne la vitesse, une exécution rapide de system.time avec votre fonction a rapporté l' utilisateur: 5.42, système: 0.09, écoulé 5.52 , tandis que l' st_intersection()approche était utilisateur: 1.18, système: 0.05, écoulé 1.23 sur votre jeu de données. (Mon environnement est probablement différent du vôtre ... je n'en suis pas sûr.)
Kazuhito
C'est intéressant - l'approche st_intersection me prend environ 80s.
pbaylis
Gardez à l'esprit que la fonction raster :: crop, lorsqu'elle est appliquée à des objets de géométrie sp, agit comme un wrapper pour les fonctions rgeos. Quoique, un emballage très pratique. L'API GEOS fonctionne sur les objets WKT, sera donc toujours un standard pour les opérations de superposition sf.
Jeffrey Evans
1
Et cela change au fil du temps, sf a maintenant "l'indexation spatiale" intégrée dans 0.5-1 cran.r-project.org/web/packages/sf/news.html donc est probablement maintenant plus rapide que sp / rgeos.
mdsumner
1
sfcomprend maintenant st_crop, voir ma réponse pour plus de détails.
AF7
1

@ solution de mdsumner en fonction. Fonctionne si rastaest un RasterBrick, une extension, une 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)))
}

Il jette les informations crs du raster car je ne sais pas comment convertir un raster crs () en st_crs ()

Sur ma machine et pour mon échantillon de données, cela a des performances équivalentes à celles raster::cropd'une version SpatialLinesDataFrame des données.

La solution de @ pbaylis est environ 2,5 fois plus lente:

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

Edit: le commentaire de Somebodies suggère spex , qui produit des SpatialPolygons avec les crs du rasta, s'il a un crs.

Ce code utilise la même méthode 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
la source
sf a maintenant une st_cropfonction qui mérite probablement d'être vérifiée.
cmc