Ответы:
Пик был создан для таких проблем. Думайте об этом как о версии «con» «switch» (или «case»), которая является реализацией алгебры карт «if ... else».
Например, если есть 3 перекрывающихся растра, синтаксис (Python) будет выглядеть так:
inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])
Обратите внимание, что pick
индексирование начинается с 1, а не с 0.
(см. ветку комментариев)
Чтобы справиться со значениями NoData, сначала вам нужно отключить обработку NoData в ArcGIS. Сделайте это, создавая сетки, которые имеют специальное (но действительное) значение вместо NoData, например 99999 (или что-то еще: но убедитесь, что выбрано значение, которое больше любого допустимого числа, которое может появиться: это пригодится позже) , Это требует использования запроса IsNull, как в
p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)
Например, рассмотрим случай этих однорядных сеток (NoData отображается как «*»):
inRas01: 1 2 19 4 * * * *
inRas02: 9 2 * * 13 14 * *
inRas03: 17 * 3 * 21 * 23 *
В результате вместо каждого "*" ставится 99999.
Затем представьте все эти растры как плоские массивы деревянных блоков с NoData, соответствующими отсутствующим блокам (отверстиям). Когда вы сложите эти растры вертикально, блоки упадут в любые отверстия под ними. Нам нужно такое поведение, чтобы избежать выбора значений NoData: нам не нужны вертикальные пропуски в стопках блоков. Порядок блоков в каждой башне на самом деле не имеет значения. Для этого мы можем получить каждую башню, упорядочив данные :
q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])
В примере мы получаем
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
Обратите внимание, что ранги находятся от самого низкого до самого высокого, так что q01 содержит самые низкие значения в каждом местоположении, q02 содержит второе-самое низкое и т. Д. Коды NoData не начинают появляться, пока не будут собраны все действительные числа, потому что эти коды имеют больше , чем любые действительные числа.
Чтобы избежать выбора этих кодов NoData во время случайного выбора, вам нужно знать, сколько блоков сложено в каждом месте: это говорит нам, сколько встречается допустимых значений. Один из способов справиться с этим - подсчитать количество кодов NoData и вычесть их из общего числа сеток выбора:
n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])
Это дает
n0: 3 2 2 1 2 1 1 0
Для обработки случаев, когда n = 0 (так что ничего не доступно для выбора), установите для них значение NoData:
n = SetNull(n0 == 0, n0)
Сейчас же
n: 3 2 2 1 2 1 1 *
Это также гарантирует, что ваши (временные) коды NoData исчезнут в окончательном расчете. Генерация случайных значений от 1 до n:
inPositionRaster = 1 + int(n * CreateRandomRaster())
Например, этот растр может выглядеть
inPositionRaster: 3 2 1 1 2 1 1 *
Все его значения лежат между 1 и соответствующим значением в [n].
Выберите значения точно так же, как и раньше:
selection = Pick(inPositionRaster, [q01, q02, q03])
Это приведет к
selection: 17 2 3 4 21 14 23 *
Чтобы убедиться, что все в порядке, попробуйте выбрать все выходные ячейки, которые имеют код NoData (99999 в этом примере): их не должно быть.
Хотя в этом запущенном примере для выбора используются только три сетки, я написал его так, чтобы его можно было легко обобщить для любого числа сеток. При большом количестве сеток написание скрипта (для повторения повторяющихся операций) будет иметь неоценимое значение.
pick
: если inPositionRaster и выбранный растр оба имеют допустимые значения в ячейке, то вероятный результат для этой ячейки должно быть значение выбранного растра, независимо от того, что может содержать любой из других растров). О каком альтернативном поведении вы думаете?
Использование python и ArcGIS 10 и использование функции con, которая имеет следующий синтаксис:
Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})
Идея здесь состоит в том, чтобы увидеть, если значение в случайном растре меньше 0,5, если оно выбрано raster1, в противном случае выберите raster2. NoData
+ data =, NoData
так что сначала установите эти переменные для любых значений NoData
в 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
РЕДАКТИРОВАТЬ: Просто понял, что вы не добавляете NoData
значения, так что кусок может быть опущен.
Con(IsNull(ras1), 0, ras2)
NoData
? Это просто чтобы убедиться, что они не выбраны при случайном выборе?
Я бы просто создал случайный растр ( справку ) того же размера и размера ячейки. Затем с помощью CON ( справка ) установите его для выбора значения из 1-го растра, если ячейка из рандомизированного растра имеет значение <128 (если случайный растр будет 0 - 255), в противном случае выберите значение из 2-го растра.
Надеюсь, что это имеет смысл :)