Erstellen eines Rasters durch zufällige Auswahl des Zellenwerts aus mehreren überlappenden Rastern?

10

Ich verwende ArcGIS Desktop 10 mit der Erweiterung Spatial Analyst.

Wie kombiniere ich mehrere Raster zu einem und wähle immer zufällig aus den Werten überlappender Zellen aus?

Ich habe ein Bild, das dies besser erklären könnte:

Beispiel

Sam
quelle

Antworten:

7

Pick wurde für solche Probleme erstellt. Stellen Sie sich das als "switch" (oder "case") Version von "con" vor, der Map-Algebra-Implementierung von "if ... else".

Wenn es zum Beispiel 3 überlappende Raster gibt, würde die (Python-) Syntax so aussehen

inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])

Beachten Sie, dass pickdie Indizierung bei 1 beginnt, nicht bei 0.


Bearbeiten

(siehe den Kommentarthread)

Um mit NoData-Werten fertig zu werden, müssen Sie zuerst die NoData-Behandlung von ArcGIS deaktivieren. Erstellen Sie dazu Raster, die anstelle von NoData einen speziellen (aber gültigen) Wert haben, z. B. 99999 (oder was auch immer: Wählen Sie jedoch einen Wert, der größer ist als eine gültige Zahl, die angezeigt werden kann. Dies ist später hilfreich.) . Dies erfordert die Verwendung der IsNull-Anforderung wie in

p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)

Betrachten Sie beispielsweise den Fall dieser einzeiligen Gitter (NoData wird als "*" angezeigt):

inRas01:  1  2 19  4  *  *  *  *
inRas02:  9  2  *  * 13 14  *  *
inRas03: 17  *  3  * 21  * 23  *

Das Ergebnis ist, dass anstelle jedes "*" ein 99999 eingesetzt wird.

Stellen Sie sich als nächstes alle diese Raster als flache Anordnungen von Holzblöcken vor, wobei NoData fehlenden Blöcken (Löchern) entspricht. Wenn Sie diese Raster vertikal stapeln, fallen Blöcke in Löcher darunter. Wir brauchen dieses Verhalten, um die Auswahl von NoData-Werten zu vermeiden: Wir wollen keine vertikalen Lücken in den Blockstapeln. Die Reihenfolge der Blöcke in jedem Turm spielt keine Rolle. Zu diesem Zweck können wir jeden Turm erhalten, indem wir die Daten ordnen :

q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])

Im Beispiel erhalten wir

q01:      1     2     3     4    13    14    23 99999
q02:      9     2    19 99999    21 99999 99999 99999
q03:     17 99999 99999 99999 99999 99999 99999 99999

Beachten Sie, dass die Ränge vom niedrigsten zum höchsten sind, sodass q01 an jeder Stelle die niedrigsten Werte enthält, q02 die zweitniedrigsten usw. Die NoData-Codes werden erst angezeigt, wenn alle gültigen Zahlen erfasst wurden, da diese Codes vorhanden sind sind größer als alle gültigen Zahlen.

Um zu vermeiden, dass diese NoData-Codes während der zufälligen Auswahl ausgewählt werden, müssen Sie wissen, wie viele Blöcke an jedem Ort gestapelt sind. Dies gibt an, wie viele gültige Werte auftreten. Eine Möglichkeit, dies zu handhaben, besteht darin, die Anzahl der NoData-Codes zu zählen und diese von der Gesamtzahl der Auswahlgitter zu subtrahieren:

n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])

Dies ergibt

n0:       3 2 2 1 2 1 1 0

Um die Fälle zu behandeln, in denen n = 0 ist (es steht also nichts zur Auswahl zur Verfügung), setzen Sie sie auf NoData:

n = SetNull(n0 == 0, n0)

Jetzt

n:        3 2 2 1 2 1 1 *

Dies garantiert auch, dass Ihre (temporären) NoData-Codes bei der endgültigen Berechnung verschwinden. Generiere Zufallswerte zwischen 1 und n:

inPositionRaster = 1 + int(n * CreateRandomRaster())

Zum Beispiel könnte dieses Raster so aussehen

inPositionRaster: 3 2 1 1 2 1 1 *

Alle seine Werte liegen zwischen 1 und dem entsprechenden Wert in [n].

Wählen Sie die Werte genau wie zuvor aus:

selection = Pick(inPositionRaster, [q01, q02, q03])

Dies würde dazu führen

selection:       17  2  3  4 21 14 23  *

Um zu überprüfen, ob alles in Ordnung ist, wählen Sie alle Ausgabezellen aus, die den NoData-Code haben (in diesem Beispiel 99999): Es sollten keine vorhanden sein.

Obwohl in diesem Beispiel nur drei Gitter zur Auswahl verwendet werden, habe ich es so geschrieben, dass es leicht auf eine beliebige Anzahl von Gittern verallgemeinert werden kann. Bei vielen Gittern ist das Schreiben eines Skripts (um die wiederholten Operationen zu durchlaufen) von unschätzbarem Wert.

whuber
quelle
Wissen Sie, wie ich die NoData-Werte aus den Berechnungen ignorieren kann (mit Raster Calculator und Python)?
Sam
Sam, "Ignoriere" wie genau? Ich glaube, das Standardverhalten besteht darin, NoData überall dort auszugeben, wo ein oder mehrere Eingabe-Raster NoData sind (aber ich bin mir nicht ganz sicher, pickwenn: inPositionRaster und das ausgewählte Raster beide gültige Werte in einer Zelle haben, dann plausibel das Ergebnis für diese Zelle sollte der Wert des ausgewählten Rasters sein, unabhängig davon, was die anderen Raster enthalten können). An welches alternative Verhalten denken Sie?
whuber
Ich brauche es, um nur aus den ganzen Zahlenwerten auszuwählen. Nehmen wir an, ich habe drei Raster. Für eine Zelle lauten ihre Werte wie folgt: 4,5, NoData. Ich möchte, dass der Outraster entweder eine 4 oder eine 5 in dieser Zelle hat, aber niemals die NoData.
Sam
Ich habe Probleme, dieses 1 + Int (n * CreateRandomRaster ()) zum Laufen zu bringen.
Sam
"Ärger" in welchem ​​Sinne? Bitte erläutern!
whuber
4

Verwenden von Python und ArcGIS 10 und Verwenden der con- Funktion mit der folgenden Syntax:

Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})

Die Idee hier ist zu sehen, ob der Wert im zufälligen Raster kleiner als 0,5 ist, wenn es Raster1 ist, andernfalls wählen Sie Raster2. NoData+ data = NoDataalso setze diese zuerst umklassifiziere alle Werte mit NoDataauf 0:

import arcpy
from arcpy import env
from arcpy.sa import *
env.workspace = "C:/sapyexamples/data"

ras1_NoNull = Con(IsNull("elevation1"),0, "elevation1")  # remove NoData
ras2_NoNull = Con(IsNull("elevation2"),0, "elevation2")  # remove NoData
randRaster = CreateRandomRaster(100, 2, Extent(0, 0, 150, 150)) # raster generated between 0 and 1; 100 is seed value

outCon = Con(randRaster < 0.5, ras1_NoNull,  ras2_NoNull)  

outCon.save("C:/outcon.img")   # save raster

BEARBEITEN: Ich habe gerade festgestellt, dass Sie die NoDataWerte nicht hinzufügen , damit das Teil weggelassen werden kann.

djq
quelle
Ich arbeite immer noch an meinen Python-Fähigkeiten. Gibt es eine Möglichkeit, dies in Raster Calculator einzugeben, die auch die NoData-Werte vom Prozess ausschließt? Ich habe 10 Raster und einige haben NoData, während andere Werte haben.
Sam
Ich denke, Sie können Bedingungen mit so etwas im Raster-Rechner Con(IsNull(ras1), 0, ras2)
erstellen
Leider schließt dies NoData-Werte nicht aus: Es ersetzt sie nur durch Nullen. In einigen Fällen könnte das angebracht sein, aber wahrscheinlich nicht hier!
whuber
hmm, guter Punkt @whuber. Was bedeutet es also auszuschließen NoData? Ist es nur um sicherzustellen, dass sie bei der zufälligen Auswahl nicht ausgewählt werden?
DJQ
So habe ich es interpretiert (siehe meine bearbeitete Antwort in diesem Thread), aber es bleibt eine gute Frage. Das Ignorieren der ND-Werte auf diese Weise führt dazu, dass die verbleibenden Gitter mit größerer Wahrscheinlichkeit ausgewählt werden, was eine unerwünschte Nebenwirkung sein kann. Es hängt alles vom Zweck der Berechnung ab.
whuber
1

Ich würde nur ein zufälliges Raster ( Hilfe ) mit dem gleichen Umfang und der gleichen Zellengröße erstellen . Verwenden Sie dann CON ( Hilfe ), um den Wert aus dem 1. Raster auszuwählen, wenn die Zelle aus dem zufälligen Raster einen Wert <128 hat (wenn ein zufälliges Raster 0 - 255 wäre), andernfalls wählen Sie einen Wert aus dem 2. Raster.

Hoffe das macht Sinn :)

Jareks
quelle
Wissen Sie, wie Sie nur aus den Rastern mit Werten auswählen können? Zum Beispiel gibt es in meiner Abbildung vier 2er und zwei 3er, die sich mit NoData überschneiden. Ich möchte sicherstellen, dass nur aus diesen Rastern mit Werten in einer Zelle und nicht aus den NoData ausgewählt wird.
Sam
Entschuldigung, dass Sie nicht geantwortet haben. Haben Sie immer noch Probleme mit dem NoData-Problem?
Jareks