Abrufen von Rasterwerten aus einer Polygon-Überlagerung in Opensource GIS-Lösungen

16

Ich habe zwei Schichten. Eine polygonförmige Ebene mit vielen Kacheln und eine Rasterebene mit CORINE 2006- Landbedeckung mit vielen Kategorien in einer Farbkarte. Ich möchte für jedes Polygon in der Formebene eine Summe jeder Landbedeckungskategorie der Rasterebene erhalten.

Zum Beispiel gibt es ein Polygon mit der ID '2' und ich möchte Attribute wie dieses für dieses Polygon (in Prozent oder Quadratmetern):

  • Ackerland: 15%
  • Wald: 11%
  • Straßen: 2% (... und so eine)

Ich habe versucht, es in Gras, QGIS (keine Funktion), Saga (fasst nur jeden auf einen Gesamtwert zusammen) r (Gesamtsumme) zu tun, aber ich habe immer noch keine Lösung gefunden. Die meisten Plugins (zonale Statistiken in QGIS) unterstützen nur 0-1 Raster-Layer. v.rast.stats hat auch nicht geholfen. Ich bin offen für jede gute und clevere Lösung !. Vielleicht habe ich sogar einen falschen Ansatz gewählt oder Fehler gemacht.

In Arcgis ist diese Aufgabe recht einfach, wenn ich mich recht erinnere, aber ich vermisse immer noch eine gute Lösung für Ihren alltäglichen Linux-Benutzer.

Ich verwende ein Debian-Linux-System und aus diesem Grund kann ich nur Programme für dieses Betriebssystem verwenden.


EDIT: Weil diese Frage noch so viele Aufrufe und Besucher hat: Ich habe ein QGIS-Plugin geschrieben, das auch die Landbedeckung der Rasterebene berechnen kann. Ich habe noch kein Polygon-Overlay codiert, aber es ist definitiv geplant. Finden Sie das Plugin hier und installieren Sie die Scipy Bibliothek zuerst.

Brachvogel
quelle
Es kann definitiv in R gemacht werden, es ist nur eine Frage der Funktion. Sie müssen jedes Polygon mit dem Raster überlagern und dann table () verwenden, um eine Zusammenfassung der "Cookie-Cut" -Pixel zu erhalten. Pakete raster, rgdal und rgeos können nützlich sein. Lesen Sie die "R Spatial Task View" (Google wird es finden)
Spacedman
sicher, aber wie kann ich eine solche Zusammenfassung bekommen. Sie können mit! Is.na (Überlagerung (Poly, Raster)) leicht eine Polygonebene mit einer Rasterebene überlagern, aber mit Befehlen wie "Extrahieren" kann ich nur die Gesamtfläche im Pixel mit Cookie-Cut berechnen und nicht die verschiedenen Kategorien einer Farbkarte . Ich kannte keine Rgeos, aber ich schaute durch die API und fand keine Funktion, um dies zu tun.
Brachvogel
Überprüfen Sie r.univar in GRASS, siehe grasswiki.osgeo.org/wiki/Zonal_statistics
markusN
Hallo! Vielen Dank, dass Sie ein QGIS-Plugin erstellt haben! Ich wollte nur erwähnen, dass das Plugin abstürzt (> 13000 Polygone). Es wäre großartig, wenn es die Aufgabe aufteilen würde, nicht abstürzen zu müssen. Und es wäre wunderbar, die Option zu haben, alle Klassen auf einmal hinzuzufügen (z. B. erhält die Attributtabelle zwei neue Felder LandcoverID und Landcover%, in denen beide eine CSV-Liste mit den Werten enthalten) :)
Mfbaer
@Joran: Wenn Sie glauben, dass dies ein Fehler ist, erstellen Sie einen Fehlerbericht, anstatt diesen in einem Kommentar zu schreiben ( github.com/Martin-Jung/LecoS/issues ). Darüber hinaus 1) ist es nicht die Aufgabe der Plugins, Ihre Aufgaben zu serialisieren oder stapelweise zu verarbeiten. Führen Sie es dann auf kleineren Teilmengen aus. 2) Sicher. Es gäbe viele wundervolle Dinge hinzuzufügen. Code ist Open Source, zögern Sie nicht, ihn zu codieren :)
Curlew

Antworten:

13

Verwenden Sie 'extract', um Polygon-Features aus einem SpatialPolygonsDataFrame (der mit maptools: readShapeSpatial aus einem Shapefile gelesen werden kann) in einem Raster zu überlagern, und verwenden Sie dann 'table', um eine Zusammenfassung zu erstellen. Beispiel:

> c=raster("cumbria.tif") # this is my CORINE land use raster
> summary(spd)
Object of class SpatialPolygonsDataFrame
[...]
> nrow(spd)  # how many polygons:
[1] 2
> ovR = extract(c,spd)
> str(ovR)
List of 2
 $ : num [1:542] 26 26 26 26 26 26 26 26 26 26 ...
 $ : num [1:958] 18 18 18 18 18 18 18 18 18 18 ...

Mein erstes Polygon umfasst also 542 Pixel und mein zweites 958. Ich kann sie alle zusammenfassen:

> lapply(ovR,table)
[[1]]

 26  27 
287 255 

[[2]]

  2  11  18 
 67  99 792 

Also ist mein erstes Polygon 287 Pixel der Klasse 26 und 255 Pixel der Klasse 27. Einfach genug, um zu addieren und zu dividieren und mit 100 zu multiplizieren, um Prozentsätze zu erhalten.

Raumfahrer
quelle
Toll, vielen Dank für die Mühe. Ich werde das versuchen und zurück berichten :-)
Curlew
6

Ich wollte mich melden und hier bin ich. Die Lösung von Spacedman funktionierte hervorragend und ich konnte alle Informationen für jedes Polygon in meiner Form exportieren. Nur für den Fall, dass jemand das gleiche Problem hat, hier ist, wie ich vorangegangen bin:

...
tab <- apply(ovR,table)
# Calculate percentage of landcover types for each polygon-field.
# landcover is a datastream with the names of every polygon
for(i in 1:length(tab)){
 s <- sum(tab[[i]])
 mat <- as.matrix(tab[[i]])
 landcover[i,paste("X",row.names(mat),sep="")] <- as.numeric(tab[[i]]/s)
}
Brachvogel
quelle
3

Wenn ich richtig verstehe, was Sie wollen, und vorausgesetzt, Sie haben die Vektorebene 'mypolygonlayer' und die Rasterebene 'corina' bereits in Ihrer GRASS GIS-Datenbank:

Zuerst würde ich Vektor in Raster konvertieren. Die Katze stellt sicher, dass Sie eine eindeutige Kennung pro Polygon haben. Wenn Sie eine Spalte mit einem eindeutigen numerischen Bezeichner haben, können Sie stattdessen diese Spalte verwenden. Die Beschriftungsspalte ist optional:

v.to.rast input = mypolygonlayer layer = 1 output = mypolygons use = cat labelcolumn = NameMappingUnit

Führen Sie dann r.stats aus, um Ihre Statistiken abzurufen:

r.stats -a -l input = mypolygons, corina separator =; output = / home / paulo / corinastats.csv

Der letzte Schritt besteht darin, die Datei corinastats.csv in z. B. LibreOffice zu öffnen und eine Pivot-Tabelle zu erstellen oder mit R eine Kreuztabelle zu erstellen

Ecodiv
quelle
3

Ich weiß, dass dieser Beitrag ziemlich alt ist, aber ich musste kürzlich die gleiche Art von Analyse durchführen, aber das Herunterladen von Programmen wie R ist ein bisschen mühsam auf meinem Arbeitscomputer und muss genehmigt werden. Nachdem ich viele Stunden lang nach einer Methode gesucht hatte, die ich nur mit QGis und Excel verwenden konnte, stellte ich fest, dass diese Methode für mich am besten funktionierte und wollte sie Menschen in der gleichen Situation anbieten.

  1. Polygon in Rasterebene ausschneiden (Raster → Extraktion → Clipper: Eingabedatei = Rasterebene, wählen Sie den Namen und den Speicherort der Ausgabe, klicken Sie auf Maskenebene, wählen Sie Ihr Polygon → OK)

  2. Polygonisieren Sie die Clipper-Ebene (Raster → Konvertierung → Polygonisieren: Eingabedatei = Ihre Clip-Ebene, Ausgabe speichern → OK)

  3. Berechnung der Pixelanzahl (Klicken Sie auf die soeben erstellte Formdatei → Feldrechner öffnen: Kreuzen Sie „Neues Feld erstellen“ an und fügen Sie den Feldnamen hinzu, Funktion = Geometrie → Fläche → OK). Sie sollten jetzt eine neue Spalte in Ihrer Attributtabelle haben, die die Anzahl der Pixel angibt.

  4. Polygonebene speichern (Rechtsklick auf Polygonebene, speichern unter: Format = DBF-Datei, speichern unter → ok)

  5. Zusammenfassen der Pixelanzahl für jeden Lebensraum (excel starten, Datei öffnen, wenn Sie keine Titel haben, fügen Sie jetzt für jede Spalte einen hinzu, klicken Sie auf eine leere Zelle, gehen Sie zur Registerkarte DATEN, konsolidieren Sie, stellen Sie sicher, dass es sich um eine Summe handelt, klicken Sie auf roter Pfeil neben "Durchsuchen ..." und wählen Sie zwei Spalten aus (Titel eingeschlossen), klicken Sie auf "Hinzufügen" und aktivieren Sie die Kontrollkästchen "Obere Zeile" und "Linke Spalte" → OK)

  6. Wenn Sie wie ich viele Polygone analysieren müssen und diese in derselben Tabelle vergleichen müssen, ist dieser Schritt hilfreich. Listen Sie in einer neuen Excel-Arbeitsmappe Ihre Lebensraumnummern in Spalte A (für mich 1 bis 48) auf und platzieren Sie die beiden Spalten, die Sie gerade konsolidiert haben, in Spalte B und C (Lebensraum in B und Pixelanzahl in C). Schreiben Sie in Zelle D1 die folgende Formel: = IFNA (INDEX (C: C; MATCH (A2; B: B; 0)); "") und ziehen Sie (oder doppelklicken Sie auf die rechte untere Ecke) bis zu Ihrem letzten Wert (falls ja) Sie haben 48 Lebensräume bis zur Zelle D48). Die Anzahl der Pixel befindet sich nun in den entsprechenden Zellen Ihres Lebensraums und Sie können diesen Vorgang für alle Ihre Polygone wiederholen.

Emily
quelle
2

Wie wäre es, wenn Sie die CORINE-Daten mit QGIS ( Raster> Konvertieren> Polygonisieren ) in ein Vektorpolygon-Dataset konvertieren und dann die Union-Funktion ( Vektor> Geoverarbeitungswerkzeuge> Union ) verwenden, um sie mit den Polygonen zu kombinieren. Der resultierende Vektordatensatz würde die Bereiche jeder CORINE-Klasse in jedem Polygon enthalten.

Andy Harfoot
quelle
danke für diesen vorschlag. Ich habe noch nicht über die Vektorunion nachgedacht. Vielleicht werde ich das versuchen, wenn die R-Verarbeitung irgendwie fehlschlägt.
Brachvogel
0

QGIS.

Im QGIS-Trunk ist eine andere Version von ZonalStats verfügbar, die als Zonal Statistics bezeichnet wird.

Dies führt die von Ihnen gewünschte Funktion aus.

Was den Workflow angeht, ist mir nicht klar, wie viele Raster Sie haben oder sind sie nur Bands in einem Raster?

Willy
quelle
Danke für den Kommentar, aber Zonal Statistics isst nur Raster ohne Kategorien. Ich benutze QGIS Trunk 1.9
Brachvogel
0

Im Gegensatz zu den meisten Antworten oben würde ich argumentieren, dass die bessere Option darin besteht, Ihre Polygone zu rastern und dann mit zwei Raster-Datensätzen anstelle von zwei Polygon-Datensätzen zu arbeiten. Dies ist viel weniger verarbeitungsintensiv und daher die einzige einfach zu implementierende Lösung für die Verarbeitung großer Raster und großer Polygondateien in R.

Nachdem Sie Ihre Polygone im exakt gleichen Umfang und in der gleichen Auflösung wie die Rasterdaten gerastert haben, können Sie die hier erläuterten Zusammenfassungsstatistiken tabellieren. Dies ist sinnvoll, wenn Ihr Raster in den Speicher passt (kleine / mittlere Rasterebenen), oder Sie können jede Kategorie mit der reclassFunktion binarisieren und dann zonalStatistiken für jede Klasse berechnen . Hier ist eine Lösung, die die Rasterungs- und Zonenstatistik in eine Funktion integriert und mit sehr großen Datasets funktioniert.

joaoal
quelle