Correzione di fori orfani in R


18

Sto cercando di eseguire un'unione su un campo comune dopo aver unito due shapefile adiacenti. Gli shapefile finiscono con almeno un sottile frammento di spazio tra loro. Quando provo un'unione ottengo il seguente errore di foro orfano:

Errore in createPolygonsComment (p): rgeos_PolyCreateComment: foro orfano, impossibile trovare il poligono contenente per il foro all'indice 17

Ho caricato un esempio riproducibile su Dropbox a questo link .

Ecco il codice per ricreare il problema:

#loading required packages
require(sp)    
require(rgdal)
require(maptools)
require(rgeos)

#load example data, set "dsn=" to your working directory or specify the path
example <- readOGR(dsn=".",layer="ReproducibleExample")

#Attempting a UnionSpatialPolygons based on the COUNTY field
example.df <- as(example, "data.frame")
countycol <- example.df$COUNTY
example.diss <- unionSpatialPolygons(example, countycol)

Ritorna:

Errore in createPolygonsComment (p): rgeos_PolyCreateComment: foro orfano, impossibile trovare il poligono contenente per il foro all'indice 17

Provando la correzione proposta qui e qui :

slot(example, "polygons") <- lapply(slot(example, "polygons"), checkPolygonsHoles)

Questo restituisce lo stesso errore che proviene dal tentativo di unione ma con un numero di indice diverso:

rgeos_PolyCreateComment: foro orfano, impossibile trovare il poligono contenente il foro all'indice 30

Provare la correzione proposta nel tutorial utile di Roger Bivand

fix <- slot(example, "polygons")
fixa <- lapply(fix, checkPolygonsHoles)

Restituisce lo stesso errore sull'indice 30 come sopra.

Altri hanno sollevato questo problema qui e qui , e mentre le soluzioni sopra indicate sembrano funzionare in alcuni casi, altri non vengono risolti. Un utente ha utilizzato QGIS per risolvere il problema e l'altro ha risolto 2 degli 3 elementi, ma nessuna risoluzione per quello finale.

Sembra che le persone continuino ad avere problemi nonostante questo codice funzioni di tanto in tanto. Qualcuno ha trovato una soluzione all'interno di R?

Ho eseguito lo strumento "Ripara geometria" in ArcGIS e il problema è stato corretto, ma sembra che ci dovrebbe essere una correzione in R.


Senza i tuoi dati, è difficile dire dov'è il problema.

@Pascal, ho appena caricato un link dropbox con uno shapefile ridotto di 10mb zippato e 16mb decompresso che riprodurrà il problema. Non ero sicuro di come fornire i dati poiché l'originale era di 1,5 GB, ma sono riuscito a utilizzare ArcGIS per restringere il problema a un file più piccolo. Esiste un buon protocollo per creare e condividere esempi riproducibili di dimensioni gestibili?
Luke Macaulay,

Provare approcci diversi con R non ha funzionato. E Qgis si sta bloccando quando si controllano le geometrie.

Risposte:


25

Ho analizzato i problemi di geometria nei dati allegati e sembra che non lo abbia SOLO orphaned holesma anche geometry validity issues. È vero che an orphaned holeè in qualche modo un problema di validità geometrica, ma i rgeos non la gestiscono allo stesso modo, come per i fori orfani, viene generato un errore, anziché un semplice avviso. Come indicato, sono suggerimenti per controllare i fori poligonali, ma non sempre hanno successo quando applicati per correggere i fori orfani.

Quindi, andiamo:

  1. pulisci i tuoi dati (che è necessario se desideri fare geoprocessing come unione)

  2. utilizzare i dati puliti con il processo del sindacato

1. Pulizia della geometria La riparazione delle geometrie in R può talvolta essere difficile, quindi ho provato a creare un pacchetto R sperimentale (vedi https://github.com/eblondel/cleangeo ) che intende facilitare la pulizia degli spoggetti (al momento limitato a forme poligonali). Puoi installare il pacchetto con:

require(devtools)
install_github("eblondel/cleangeo")
require(cleangeo)

Per iniziare, è bene vedere quali sono i problemi di geometria con i dati di origine. Per questo, è possibile eseguire quanto segue (i dati sono di grandi dimensioni in modo che possa richiedere del tempo):

#get a report of geometry validity & issues for a sp spatial object
report <- clgeo_CollectionReport(sp)
summary <- clgeo_SummaryReport(report)
issues <- report[report$valid == FALSE,]

Con questo, vedrai che i tuoi dati hanno 2 tipi di problemi: orphaned holese geometry validity issues. Entrambi (e non solo i buchi orfani) probabilmente faranno unionfallire il processo, quindi i dati dovrebbero essere puliti prima, in modo automatico quando possibile. Per una riproduzione veloce, il primo codice di esempio riportato di seguito prende solo il sottoinsieme di funzionalità contrassegnate come sospette (tranne l'ultima, con indice = 9002 nei dati originali - vedere la mia nota sotto su questo)

#get suspicious features (indexes)
nv <- clgeo_SuspiciousFeatures(report)
mysp <- sp[nv[-14],]

#try to clean data
mysp.clean <- clgeo_Clean(mysp, print.log = TRUE)

#check if they are still errors
report.clean <- clgeo_CollectionReport(mysp.clean)
summary.clean <- clgeo_SummaryReport(report.clean)

Se clgeo_Cleanfunziona bene, dovresti ottenere tutte le geometrie valide ora. Puoi applicarlo al set di dati completo (tranne l'indice di funzionalità = 9002)

#try to clean data
mysp <- sp[-9002,]
mysp.clean <- clgeo_Clean(mysp, print.log = TRUE)

#check if they are still errors
report.clean <- clgeo_CollectionReport(mysp.clean)
summary.clean <- clgeo_SummaryReport(report.clean)

2. Processo dell'Unione Ora, vediamo se unionfunziona su questo set di dati:

#Attempting a UnionSpatialPolygons based on the COUNTY field
mysp.df <- as(mysp, "data.frame")
countycol <- mysp.df$COUNTY
mysp.diss <- unionSpatialPolygons(mysp.clean, countycol)

Nota: come detto prima, ho rimosso una funzione (indice = 9002). Con la trama: plot(sp[9002,])vedrai che questa funzione è molto (molto) complessa. L'ho escluso dal campione solo perché il controllo dei fori stava impiegando troppo tempo. Vediamo ora se lo stesso problema si verifica usando readShapePoly(da maptools) per leggere i dati ...

3. Passa a readShapePoly vs. readOGR per la lettura dei dati (AGGIORNAMENTO)

readOGRnon è l'unica funzione disponibile per leggere gli shapefile. Puoi anche usare readShapePolydal maptoolspacchetto, generalmente più performante del primo:

require(maptools)
mysp <- readShapePoly("ReproducibleExample.shp")

Oltre a correre più veloce:

  • se si utilizza il codice sopra basato su clgeo_CollectionReport, non vi è alcun problema di fori orfani, ma ancora problemi di geometria.

  • Anche la pulizia della geometria clgeo_Cleanfunziona bene e ora non si blocca con l'indice di funzionalità 9002

  • E ... il processo sindacale funziona.

Vedi sotto il risultato della trama:

#plot the result
plot(mysp, border= "lightgray")
plot(mysp.diss, border="red", add = TRUE)

Risultato dell'Unione

Conclusione : preferisci i maptools per leggere i tuoi dati shapefile e considera l'utilizzo di cleangeo per pulire i tuoi dati prima di qualsiasi geoprocessing.


Grazie eblondel! Lo proverò. Grazie per lo sviluppo del pacchetto!
Luke Macaulay,

Ciao eblondel, ha funzionato bene, ma volevo farti sapere che correggendo la geometria, spesso si creava un poligono molto grande quando si tratta di funzioni complesse e complesse. Ad esempio, una rete stradale è stata corretta con un grande poligono che era sostanzialmente l'estensione della rete. Non sono sicuro di quanto sia facile correggerlo, ma volevo farti sapere.
Luke Macaulay,

Wow. Pacchetto molto impressionante. Deve essere stato un sacco di lavoro.
nograpes,

3
Grazie @nograpes per il tuo feedback. Ho creato questo pacchetto da zero quando è stato pubblicato questo problema, anche perché la pulizia delle geometrie non è sempre un compito facile. Se sei su Github, accolgo con favore la tua "stella" :-), vorrei migliorare ulteriormente il pacchetto in futuro e possibilmente rilasciarlo su CRAN.
eblondel,

7
Solo per farti sapere che cleangeo è stato pubblicato in CRAN ( cran.r-project.org/package=cleangeo ), a tutte le persone che lo usano, sentiti libero di segnalare richieste di miglioramento o bug in Github.
eblondel,

1

Una soluzione conveniente che continua a funzionare per me in R è applicare un buffer di larghezza zero :

#loading required packages
require(sp)    
require(rgdal)
require(maptools)
require(rgeos)

#load example data, set "dsn=" to your working directory or specify the path
example <- readOGR(dsn=".",layer="ReproducibleExample")

#project your data (I'm using California Albers here) and apply a zero-width buffer
example <- spTransform(example, CRS("+init=epsg:3310"))
example <- gBuffer(example, byid = T, width = 0)

#Attempting a UnionSpatialPolygons based on the COUNTY field
example.df <- as(example, "data.frame")
countycol <- example.df$COUNTY
example.diss <- unionSpatialPolygons(example, countycol)

unionSpatialPolygons impiega un po 'di tempo con questo set di dati, ma sembra funzionare bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.