J'ai un SpatialPointsDataFrame
avec quelques données supplémentaires. Je voudrais extraire ces points à l'intérieur d'un polygone et en même temps, conserver l' SPDF
objet et ses données correspondantes.
Jusqu'à présent, j'ai eu peu de chance et j'ai eu recours à la correspondance et à la fusion via un ID commun, mais cela ne fonctionne que parce que j'ai quadrillé les données avec des IDS individuels.
Voici un exemple rapide, je recherche des points à l'intérieur du carré rouge.
library(sp)
set.seed(357)
pts <- data.frame(x = rnorm(100), y = rnorm(100), var1 = runif(100), var2 = sample(letters, 100, replace = TRUE))
coordinates(pts) <- ~ x + y
class(pts)
plot(pts)
axis(1); axis(2)
ply <- matrix(c(-1,-1, 1,-1, 1,1, -1,1, -1,-1), ncol = 2, byrow = TRUE)
ply <- SpatialPolygons(list(Polygons(list(Polygon(ply)), ID = 1)))
ply <- SpatialPolygonsDataFrame(Sr = ply, data = data.frame(polyvar = 357))
plot(ply, add = TRUE, border = "red")
L'approche la plus évidente serait d'utiliser over
, mais cela renvoie les données du polygone.
> over(pts, ply)
polyvar
1 NA
2 357
3 357
4 NA
5 357
6 357
Réponses:
De l'
sp::over
aide:Donc, si vous convertissez votre
SpatialPolygonsDataFrame
enSpatialPolygons
vous récupérez un vecteur d'index et vous pouvez sous-définir vos points surNA
:Pour les sceptiques, voici la preuve que la surcharge de conversion n'est pas un problème:
Deux fonctions - d'abord la méthode de Jeffrey Evans, puis ma version originale, puis ma conversion piratée, puis une version basée sur
gIntersects
la réponse de Josh O'Brien:Maintenant, pour un exemple réel, j'ai dispersé quelques points aléatoires sur l'
columbus
ensemble de données:Cela semble bon
Vérifiez que les fonctions font la même chose:
Et exécutez 500 fois pour l'analyse comparative:
Selon mon intuition, ce n'est pas une surcharge importante, en fait, cela pourrait être moins d'une surcharge que la conversion de tous les index de ligne en caractère et retour, ou l'exécution de na.omit pour obtenir les valeurs manquantes. Ce qui conduit d'ailleurs à un autre mode de défaillance de la
evans
fonction ...Si une ligne du bloc de données de polygones est tout
NA
(ce qui est parfaitement valide), la superposition avecSpatialPolygonsDataFrame
pour les points dans ce polygone produira un bloc de données de sortie avec tous lesNA
s, quievans()
tombera alors:MAIS
gIntersects
est plus rapide, même avec le balayage de la matrice pour vérifier les intersections dans R plutôt que dans le code C. Je soupçonne que ce sont lesprepared geometry
compétences de GEOS, créant des index spatiaux - oui, avecprepared=FALSE
cela prend un peu plus de temps, environ 5,5 secondes.Je suis surpris qu'il n'y ait pas de fonction pour renvoyer directement les indices ou les points. Quand j'ai écrit
splancs
il y a 20 ans, les fonctions de point dans le polygone avaient les deux ...la source
sp
fournit une forme plus courte pour sélectionner les entités en fonction de l'intersection spatiale, en suivant l'exemple OP:au:
Dans les coulisses, c'est court pour
La chose à noter est qu'il existe une
geometry
méthode qui supprime les attributs:over
change le comportement si son deuxième argument a des attributs ou non (c'était la confusion de OP). Cela fonctionne dans toutes les classes Spatial * danssp
, bien que certainesover
méthodes nécessitentrgeos
, voir cette vignette pour plus de détails, par exemple le cas de plusieurs correspondances pour des polygones qui se chevauchent.la source
Vous étiez sur la bonne voie avec fini. Les noms renommés de l'objet retourné correspondent à l'index de ligne des points. Vous pouvez implémenter votre approche exacte avec seulement quelques lignes de code supplémentaires.
la source
C'est ce que tu cherches?
Une remarque, lors de la modification: l'appel d'habillage à
apply()
est nécessaire pour que cela fonctionne avec desSpatialPolygons
objets arbitraires , contenant éventuellement plusieurs entités surfaciques. Merci à @Spacedman de m'avoir incité à montrer comment l'appliquer au cas plus général.la source
ply
possède plusieurs fonctionnalités, cargIntersects
renvoie une matrice avec une ligne pour chaque fonctionnalité. Vous pouvez probablement balayer les lignes pour une valeur VRAIE.apply(gIntersects(pts, ply, byid=TRUE), 2, any)
. En fait, je vais aller de l'avant et changer la réponse à cela, car elle englobe également le cas d'un seul polygone.any
. Cela pourrait être légèrement plus rapide que la version que je viens de comparer.obrien
etrowlings2
fonctionne au coude à coude, avecobrien
peut-être 2% plus rapide.pp
devrait avoir unID
qui indique dans quel polygone les points sont situés.Voici une approche possible en utilisant le
rgeos
package. Fondamentalement, il utilise lagIntersection
fonction qui vous permet d'intersecter deuxsp
objets. En extrayant les ID de ces points qui se trouvent dans le polygone, vous pouvez ensuite sous-définir votre originalSpatialPointsDataFrame
, en conservant toutes les données correspondantes. Le code est presque explicite, mais s'il y a des questions, n'hésitez pas à demander!la source
tmp
êtrepts.intersect
? En outre, l'analyse des noms de domaine renvoyés comme cela dépend du comportement non documenté.tmp
oublié de le supprimer lorsque vous avez terminé le code. En outre, vous avez raison d'analyser ledimnames
. C'était une sorte de solution rapide pour fournir à l'interrogateur une réponse rapide, et il existe sûrement de meilleures approches (et plus universelles), par exemple la vôtre :-)Il existe une solution extrêmement simple utilisant la
spatialEco
bibliothèque.Vérifiez le résultat:
la source