Ich extrahiere die Fläche und die prozentuale Abdeckung verschiedener Landnutzungstypen aus einem Raster, das auf mehreren tausend Polygongrenzen basiert. Ich habe festgestellt, dass die Extrahierungsfunktion viel schneller funktioniert, wenn ich durch jedes einzelne Polygon iteriere und es beschneide und dann das Raster auf die Größe des jeweiligen Polygons verkleinere. Trotzdem ist es ziemlich langsam und ich frage mich, ob jemand Vorschläge zur Verbesserung der Effizienz und Geschwindigkeit meines Codes hat.
Das einzige, was ich im Zusammenhang damit gefunden habe, ist die Antwort von Roger Bivand, der die Verwendung von GDAL.open()
und GDAL.close()
sowie getRasterTable()
und vorschlug getRasterData()
. Ich habe mir diese angeschaut, hatte aber in der Vergangenheit Probleme mit gdal und kenne sie nicht gut genug, um zu wissen, wie man sie umsetzt.
Reproduzierbares Beispiel:
library(maptools) ## For wrld_simpl
library(raster)
## Example SpatialPolygonsDataFrame
data(wrld_simpl) #polygon of world countries
bound <- wrld_simpl[1:25,] #name it this to subset to 25 countries and because my loop is set up with that variable
## Example RasterLayer
c <- raster(nrow=2e3, ncol=2e3, crs=proj4string(wrld_simpl), xmn=-180, xmx=180, ymn=-90, ymx=90)
c[] <- 1:length(c)
#plot, so you can see it
plot(c)
plot(bound, add=TRUE)
Schnellste Methode bisher
result <- data.frame() #empty result dataframe
system.time(
for (i in 1:nrow(bound)) { #this is the number of polygons to iterate through
single <- bound[i,] #selects a single polygon
clip1 <- crop(c, extent(single)) #crops the raster to the extent of the polygon, I do this first because it speeds the mask up
clip2 <- mask(clip1,single) #crops the raster to the polygon boundary
ext<-extract(clip2,single) #extracts data from the raster based on the polygon bound
tab<-lapply(ext,table) #makes a table of the extract output
s<-sum(tab[[1]]) #sums the table for percentage calculation
mat<- as.data.frame(tab)
mat2<- as.data.frame(tab[[1]]/s) #calculates percent
final<-cbind(single@data$NAME,mat,mat2$Freq) #combines into single dataframe
result<-rbind(final,result)
})
user system elapsed
39.39 0.11 39.52
Parallelverarbeitung
Durch die parallele Verarbeitung wurde die Benutzerzeit halbiert, der Vorteil jedoch durch die Verdoppelung der Systemzeit zunichte gemacht. Raster verwendet dies für die Extraktionsfunktion, aber leider nicht für die Zuschneide- oder Maskenfunktion. Leider verbleibt dadurch etwas mehr Gesamtzeit, da das "IO" "herumwartet".
beginCluster( detectCores() -1) #use all but one core
Code auf mehreren Kernen ausführen:
user system elapsed
23.31 0.68 42.01
Beenden Sie dann den Cluster
endCluster()
Langsame Methode: Die alternative Methode zum Erstellen eines Extrakts direkt aus der Rasterfunktion dauert viel länger, und ich bin nicht sicher, ob die Datenverwaltung das gewünschte Format annimmt:
system.time(ext<-extract(c,bound))
user system elapsed
1170.64 14.41 1186.14
Antworten:
Ich habe es endlich geschafft, diese Funktion zu verbessern. Ich fand, dass es für meine Zwecke am schnellsten war, zuerst
rasterize()
das Polygon zu verwenden undgetValues()
stattdessenextract()
. Das Rastern ist nicht viel schneller als der ursprüngliche Code zum Tabellieren von Rasterwerten in kleinen Polygonen, aber es scheint, wenn es um große Polygonbereiche geht, in denen große Raster zugeschnitten und die Werte extrahiert werden müssen. Ich fand auchgetValues()
war viel schneller als dieextract()
Funktion.Ich habe auch die Multi-Core-Verarbeitung mit herausgefunden
foreach()
.Ich hoffe, dies ist nützlich für andere Personen, die eine R-Lösung zum Extrahieren von Rasterwerten aus einer Polygon-Überlagerung wünschen. Dies ähnelt dem "Tabulate Intersection" von ArcGIS, das für mich nicht gut funktioniert hat und nach stundenlanger Verarbeitung leere Ausgaben zurückgibt , wie dieser Benutzer.
Hier ist die Funktion:
single@data$OWNER
Um es zu verwenden, passen Sie es an den Spaltennamen Ihres identifizierenden Polygons an (raten Sie, dass dies in die Funktion integriert sein könnte ...) und geben Sie Folgendes ein:quelle
getValues
der viel schneller als der war,extract
scheint nicht gültig zu sein, denn wenn Sie ihn verwendenextract
, müssen Siecrop
undrasterize
(odermask
) nicht tun . Der Code in der ursprünglichen Frage kann beides, und das sollte ungefähr die doppelte Verarbeitungszeit bedeuten.Beschleunigen Sie das Extrahieren des Rasters (Raster-Stack) von Punkt, XY oder Polygon
Tolle Antwort, Luke. Sie müssen ein R-Assistent sein! Hier ist eine sehr geringfügige Änderung, um Ihren Code zu vereinfachen (kann in einigen Fällen die Leistung geringfügig verbessern). Sie können einige Operationen vermeiden, indem Sie cellFromPolygon (oder cellFromXY für Punkte) verwenden und dann clip und getValues.
Polygon- oder Punktedaten aus Raster-Stapeln extrahieren ------------------------
quelle
Wenn ein Verlust in der Genauigkeit der Überlagerung nicht besonders wichtig ist - vorausgesetzt, es ist von vornherein genau -, können Sie in der Regel viel höhere Berechnungsgeschwindigkeiten für Zonen erzielen, indem Sie zuerst die Polygone in ein Raster konvertieren. Das
raster
Paket enthält diezonal()
Funktion, die für die beabsichtigte Aufgabe gut funktionieren sollte. Sie können jedoch immer zwei Matrizen derselben Dimension mit der Standardindizierung unterteilen. Wenn Sie Polygone pflegen müssen und die GIS-Software nichts ausmacht, muss QGIS in Bezug auf Zonenstatistiken tatsächlich schneller sein als ArcGIS oder ENVI-IDL.quelle
Ich hatte auch einige Zeit damit zu kämpfen und versuchte, den Flächenanteil der Landbedeckungsklassen einer ~ 300mx300m-Gitterkarte in einem ~ 1kmx1km-Gitter zu berechnen. Letzteres war eine Polygondatei. Ich habe die Multicore-Lösung ausprobiert, aber diese war immer noch zu langsam für die Anzahl der Gitterzellen, die ich hatte. Stattdessen ich:
Dieser Vorgang läuft ziemlich schnell und ohne Speicherprobleme auf meinem PC ab, als ich ihn auf einer Landbedeckungskarte mit> 15 Mill-Grid-Zellen bei 300 x 300 m ausprobierte.
Ich gehe davon aus, dass der oben beschriebene Ansatz auch funktioniert, wenn eine Polygondatei mit unregelmäßigen Formen und Rasterdaten kombiniert werden soll. Möglicherweise können Sie die Schritte 1 und 2 kombinieren, indem Sie die Polygondatei mit rasterize (wahrscheinlich langsam) oder gdal_rasterize direkt in ein 300 x 300-Raster rastern. In meinem Fall musste ich ebenfalls neu projizieren, also benutzte ich gdalwarp, um gleichzeitig neu zu projizieren und zu disaggregieren.
quelle
Ich muss mich dem gleichen Problem stellen, um Werte innerhalb eines Polygons aus einem großen Mosaik (50k x 50k) zu extrahieren. Mein Polygon hat nur 4 Punkte. Die schnellste Methode, die ich gefunden habe, besteht darin, ein
crop
Mosaik in einen Polygonrand zu setzen, ein Polygon in zwei Dreiecke zu triangulieren und dann zu prüfen, ob Punkte im Dreieck vorhanden sind (der schnellste Algorithmus, den ich gefunden habe). Im Vergleich zurextract
Funktion reduziert sich die Laufzeit von 20 s auf 0,5 s. Die Funktioncrop
benötigt jedoch noch ca. 2 s für jedes Polygon.Leider kann ich nicht das vollständige reproduzierbare Beispiel bereitstellen. Die folgenden R-Codes enthalten keine Eingabedateien.
Diese Methode funktioniert nur für einfache Polygone.
quelle