Respuestas:
Pick fue creado para problemas como este. Piense en ello como la versión "switch" (o "case") de "con", que es la implementación de álgebra de mapas de "if ... else".
Si hay 3 rásteres superpuestos, por ejemplo, la sintaxis (Python) se vería así
inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])
Tenga en cuenta que pick
comienza a indexar en 1, no en 0.
(ver el hilo de comentarios)
Para hacer frente a los valores de NoData, primero debe desactivar el manejo de NoData de ArcGIS. Haga esto creando cuadrículas que tengan un valor especial (pero válido) en lugar de NoData, como 99999 (o lo que sea: pero asegúrese de elegir un valor que sea mayor que cualquier número válido que pueda aparecer: esto será útil más adelante) . Esto requiere el uso de la solicitud IsNull, como en
p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)
Por ejemplo, considere el caso de estas cuadrículas de una fila (NoData se muestra como "*"):
inRas01: 1 2 19 4 * * * *
inRas02: 9 2 * * 13 14 * *
inRas03: 17 * 3 * 21 * 23 *
El resultado es poner un 99999 en lugar de cada "*".
A continuación, imagine todos estos rásteres como matrices planas de bloques de madera con NoData correspondiente a bloques faltantes (agujeros). Cuando apilas verticalmente estos rásteres, los bloques caerán en cualquier agujero debajo de ellos. Necesitamos ese comportamiento para evitar elegir valores NoData: no queremos espacios verticales en las pilas de bloques. El orden de los bloques en cada torre realmente no importa. Para este fin, podemos obtener cada torre clasificando los datos :
q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])
En el ejemplo, obtenemos
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
Tenga en cuenta que los rangos son de menor a mayor, de modo que q01 contiene los valores más bajos en cada ubicación, q02 contiene el segundo más bajo, etc. Los códigos NoData no comienzan a aparecer hasta que se recopilan todos los números válidos, porque esos códigos son más grandes que cualquier número válido.
Para evitar elegir estos códigos NoData durante la selección aleatoria, debe saber cuántos bloques se apilan en cada ubicación: esto nos dice cuántos valores válidos ocurren. Una forma de manejar esto es contar el número de códigos NoData y restarlo del número total de cuadrículas de selección:
n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])
Esto produce
n0: 3 2 2 1 2 1 1 0
Para manejar los casos donde n = 0 (por lo que no hay nada disponible para seleccionar), configúrelos en NoData:
n = SetNull(n0 == 0, n0)
Ahora
n: 3 2 2 1 2 1 1 *
Esto también garantizará que sus códigos NoData (temporales) desaparezcan en el cálculo final. Genere valores aleatorios entre 1 yn:
inPositionRaster = 1 + int(n * CreateRandomRaster())
Por ejemplo, este ráster podría verse así
inPositionRaster: 3 2 1 1 2 1 1 *
Todos sus valores se encuentran entre 1 y el valor correspondiente en [n].
Seleccione valores exactamente como antes:
selection = Pick(inPositionRaster, [q01, q02, q03])
Esto resultaría en
selection: 17 2 3 4 21 14 23 *
Para verificar que todo esté bien, intente seleccionar todas las celdas de salida que tengan el código NoData (99999 en este ejemplo): no debería haber ninguna.
Aunque este ejemplo en ejecución usa solo tres cuadrículas para seleccionar, lo he escrito de una manera que se generaliza fácilmente a cualquier número de cuadrículas. Con muchas cuadrículas, escribir un script (para recorrer las operaciones repetidas) será invaluable.
pick
: si inPositionRaster y el ráster seleccionado tienen valores válidos en una celda, entonces el resultado es plausiblemente para esa celda debe ser el valor del ráster seleccionado, independientemente de lo que pueda contener cualquiera de los otros rásteres). ¿En qué comportamiento alternativo estás pensando?
Usando python y ArcGIS 10 y usando la función con que tiene la siguiente sintaxis:
Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})
La idea aquí es ver si el valor en el ráster aleatorio es menor que 0.5, si es elegir raster1, de lo contrario, elija raster2. NoData
+ datos = NoData
así que primero establezca estos reclasifique cualquier valor con 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
EDITAR: Acabo de darme cuenta de que no estás agregando los NoData
valores para que esa pieza se pueda omitir.
Con(IsNull(ras1), 0, ras2)
NoData
? ¿Es solo para asegurarse de que no se elijan al elegir al azar?
Simplemente crearía un ráster aleatorio ( ayuda ) de la misma extensión y tamaño de celda. Luego, usando CON ( ayuda ) configúrelo para elegir el valor del primer ráster si la celda del ráster aleatorio tiene un valor <128 (si un ráster aleatorio sería 0-255), de lo contrario, elija un valor del segundo ráster.
Espero que tenga sentido :)