tampon et union dans R sans réduire à un multi-polygone

9

Je voudrais effectuer une superposition spatiale pour identifier le polygone dans lequel se situe un ensemble de points. Cependant, je veux d'abord tamponner et dissoudre les polygones, de sorte que les points situés n'importe où dans les polygones fusionnés (mais pas dans les trous) seront étiquetés de la même manière par la procédure de superposition.

Malheureusement, le processus de mise en mémoire tampon et / ou de dissolution que j'utilise réduit l' SpatialPolygonsobjet à un polygone multiple. L'utilisation gBuffercrée un multi-polygone quand byid=FALSE, mais échoue à l'union des polygones se chevauchant quand byid=TRUE. Dans ce dernier cas, la dissolution ultérieure des polygones avec gUnaryUnioncrée à nouveau un multi-polygone. La superposition SpatialPointsde ces polygones multiples fait que tous les points contenus sont signalés comme tombant dans le polygone 1.

Voici un exemple de jouet connexe avec des points tamponnés, où je voudrais faire une superposition des points avec les polygones tamponnés:

library(sp)
library(rgeos)
pts <- SpatialPoints(cbind(c(1, 1, 2, 3), c(1, 2, 1.5, 2.5))) 
plot(gBuffer(pts, width=0.6), lwd=2)
points(pts, pch=20, cex=2)
text(coordinates(pts), labels=seq_len(length(pts)), pos=4, font=2)

entrez la description de l'image ici

Et les résultats de quelques superpositions ...

  • Avec byid=FALSE:

    b <- gBuffer(pts, width=0.6) 
    over(pts, b)
    # [1] 1 1 1 1
  • Avec byid=TRUE:

    b2 <- gBuffer(pts, width=0.6, byid=TRUE) 
    over(pts, b2)
    # [1] 1 2 3 4
  • Avec byid=TRUEet après gUnaryUnion:

    b3 <- gUnaryUnion(b2)
    over(pts, b3)
    # [1] 1 1 1 1

Je cherche la bonne méthode pour atteindre le résultat 1 1 1 2, c'est-à-dire que les points 1, 2 et 3 se trouvent dans le polygone 1 (auparavant les polygones 1, 2 et 3, qui ont été fusionnés), et le point 4 tombe dans le polygone 2 (à l'origine le polygone 4 ).


ÉDITER

Mes vraies données incluent des trous et, idéalement, j'aimerais pouvoir les conserver. J'ai mis à jour les exemples de données ci-dessus pour inclure un trou après la mise en mémoire tampon.

Appliquer l'approche de @ JeffreyEvans à ces polys:

polys <- b@polygons[[1]]@Polygons
pl <- vector("list", length(polys))
for (i in 1:length(polys)) { pl[i] <- Polygons(list(polys[[i]]), i) }
b.spolys <- SpatialPolygons(pl)
row.ids <- sapply(slot(b.spolys, "polygons"), function(i) slot(i, "ID"))    
b.exploded <- SpatialPolygonsDataFrame(b.spolys, data.frame(FID=as.numeric(row.ids))) 

résulte en:

over(pts, b.exploded)

#   FID
# 1   2
# 2   2
# 3   2
# 4   1

qui est le résultat attendu (je ne suis pas trop inquiet de l'ordre des poly - 2,2,2,1vs 1,1,1,2), mais b.explodeda perdu les informations sur le trou, au lieu de cela en le représentant comme un polygone non-trou. Cela n'affecte évidemment pas le résultat pour l'exemple de jouet, mais une superposition impliquant des points situés dans le trou sera trompeuse, par exemple:

in_hole <- SpatialPoints(cbind(1.375, 1.5))
over(in_hole, b.exploded)
#   FID
# 1   2
jbaums
la source

Réponses:

7

Il s'avère que cela sp::disaggregatepeut être utilisé pour séparer les polygones à une seule partie.

pts <- SpatialPoints(cbind(c(1, 1, 2, 3), c(1, 2, 1.5, 2.5))) 
b <- gBuffer(pts, width=0.6) 
over(pts, disaggregate(b))

# [1] 1 1 1 2

in_hole <- SpatialPoints(cbind(1.375, 1.5))
over(in_hole, disaggregate(b))

# [1] NA

( raster::aggregatepeut être utilisé pour les combiner à nouveau.)

jbaums
la source
3

Je suis sympathique, c'est un peu pénible. Vous devez exploser les emplacements, de l'objet polygone gBuffer, en polygones individuels.

require(sp)
require(rgeos)
pts <- SpatialPoints(cbind(c(1, 1, 3), c(1, 2, 3))) 

b <- gBuffer(pts, width=0.6)

over(pts, b)

###########################################################
# explodes slots into individual polygons
polys <- b@polygons[[1]]@Polygons
  pl <- vector("list", length(polys))
    for (i in 1:length(polys)) { pl[i] <- Polygons(list(polys[[i]]), i) }
      b.spolys <- SpatialPolygons(pl)
        row.ids=sapply(slot(b.spolys, "polygons"), function(i) slot(i, "ID"))    
b <- SpatialPolygonsDataFrame(b.spolys, data.frame(FID=as.numeric(row.ids)) ) 
###########################################################

over(pts, b)
Jeffrey Evans
la source
Je viens de tester et cela me semble prometteur, mais mes trous ne sont plus des trous :(. Pouvons-nous adapter cela pour garder les trous avec les polys auxquels ils sont associés? (J'allais dans le même sens que votre suggestion, avec n <- length(buff@polygons[[1]]@Polygons); SpatialPolygons(mapply(function(x, y) Polygons(list(x), y), buff@polygons[[1]]@Polygons, seq_len(n)))... J'aurais dû mentionner le problème de trou dans le message, désolé.
jbaums