Conjunto original:
Crear pseudo-copia (CNTRL-arrastrar en TOC) de la misma y hacer la unión espacial uno a muchos con el clon. En este caso he utilizado la distancia de 500m. Tabla de salida:
-
Eliminar los registros de esta tabla donde PAR_ID = PAR_ID_1 - fácil.
-
Recorrer la tabla y eliminar los registros en los que (PAR_ID,PAR_ID_1 )=(PAR_ID_1, PAR_ID) de cualquier registro superior. No es tan fácil, utilice acrpy.
Calcular los centroides de las cuencas (UniqID=PAR_ID). Son nodos o red. Conéctelos mediante líneas utilizando la tabla de unión espacial. Este es un tema aparte que seguramente se ha tratado en algún lugar de este foro.
El script de abajo asume que la tabla de nodos tiene ese aspecto:
donde el MUID procede de las parcelas, P2013 es el campo a resumir. En este caso = 1 para el recuento solamente. [rcvnode] - script de salida para almacenar el ID de grupo igual a NODEREC del primer nodo del grupo/cluster definido.
Estructura de la tabla de enlaces con los campos importantes resaltados
Times almacena el peso del enlace/borde, es decir, el coste del viaje de un nodo a otro. Es igual a 1 en este caso para que el coste del viaje a todos los vecinos sea el mismo. [fi] y [ti] son el número secuencial de nodos conectados. Para rellenar esta tabla busca en este foro cómo asignar desde y hacia los nodos al enlace.
script personalizado para mi propio banco de trabajo mxd. Tiene que ser modificado, hardcoded con su nomenclatura de los campos y fuentes:
import arcpy, traceback, os, sys,time
import itertools as itt
scriptsPath=os.path.dirname(os.path.realpath(__file__))
os.chdir(scriptsPath)
import COMMON
sys.path.append(r'C:\Users\felix_pertziger\AppData\Roaming\Python\Python27\site-packages')
import networkx as nx
RATIO = int(arcpy.GetParameterAsText(0))
try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
mxd = arcpy.mapping.MapDocument("CURRENT")
theT=COMMON.getTable(mxd)
ENCONTRAR NODOS CAPA
theNodesLayer = COMMON.getInfoFromTable(theT,1)
theNodesLayer = COMMON.isLayerExist(mxd,theNodesLayer)
OBTENER LA CAPA DE ENLACES
theLinksLayer = COMMON.getInfoFromTable(theT,9)
theLinksLayer = COMMON.isLayerExist(mxd,theLinksLayer)
arcpy.SelectLayerByAttribute_management(theLinksLayer, "CLEAR_SELECTION")
linksFromI=COMMON.getInfoFromTable(theT,14)
linksToI=COMMON.getInfoFromTable(theT,13)
G=nx.Graph()
arcpy.AddMessage("Adding links to graph")
with arcpy.da.SearchCursor(theLinksLayer, (linksFromI,linksToI,"Times")) as cursor:
for row in cursor:
(f,t,c)=row
G.add_edge(f,t,weight=c)
del row, cursor
pops=[]
pops=arcpy.da.TableToNumPyArray(theNodesLayer,("P2013"))
length0=nx.all_pairs_shortest_path_length(G)
nNodes=len(pops)
aBmNodes=[]
aBig=xrange(nNodes)
host=[-1]*nNodes
while True:
RATIO+=-1
if RATIO==0:
break
aBig = filter(lambda x: x not in aBmNodes, aBig)
p=itt.combinations(aBig, 2)
pMin=1000000
small=[]
for a in p:
S0,S1=0,0
for i in aBig:
p=pops[i][0]
p0=length0[a[0]][i]
p1=length0[a[1]][i]
if p0<p1:
S0+=p
else:
S1+=p
if S0!=0 and S1!=0:
sMin=min(S0,S1)
sMax=max(S0,S1)
df=abs(float(sMax)/sMin-RATIO)
if df<pMin:
pMin=df
aBest=a[:]
arcpy.AddMessage('%s %i %i' %(aBest,sMax,sMin))
if df<0.005:
break
lSmall,lBig,S0,S1=[],[],0,0
arcpy.AddMessage ('Ratio %i' %RATIO)
for i in aBig:
p0=length0[aBest[0]][i]
p1=length0[aBest[1]][i]
if p0<p1:
lSmall.append(i)
S0+=p0
else:
lBig.append(i)
S1+=p1
if S0<S1:
aBmNodes=lSmall[:]
for i in aBmNodes:
host[i]=aBest[0]
for i in lBig:
host[i]=aBest[1]
else:
aBmNodes=lBig[:]
for i in aBmNodes:
host[i]=aBest[1]
for i in lSmall:
host[i]=aBest[0]
with arcpy.da.UpdateCursor(theNodesLayer, "rcvnode") as cursor:
i=0
for row in cursor:
row[0]=host[i]
cursor.updateRow(row)
i+=1
del row, cursor
except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
Ejemplo de salida para 6 grupos:
Necesitará el paquete del sitio NETWORKX http://networkx.github.io/documentation/development/install.html
script toma como parámetro el número requerido de clusters (6 en el ejemplo anterior). Utiliza las tablas de nodos y enlaces para hacer un gráfico con igual peso/distancia de las aristas de viaje (Times=1). Considera la combinación de todos los nodos por 2 y calcula el total de [P2013] en dos grupos de vecinos. Cuando se consigue la relación requerida, por ejemplo (6-1)/1 en la primera iteración, continúa con un objetivo de relación reducido, es decir, 4, etc. hasta 1. Los puntos de partida son de gran importancia, así que asegúrese de que sus nodos "finales" se encuentran en la parte superior de la tabla de nodos (¿ordenación?) Vea los 3 primeros grupos en el ejemplo de salida. Esto ayuda a evitar el "corte de ramas" en cada iteración siguiente.
script personalización para trabajar desde mxd:
- no es necesario importar COMMON. Es mi propia cosa, que lee mi propia tabla de entorno, donde theNodesLayer, theLinksLayer, linksFromI, linksToI especificados. Reemplace las líneas pertinentes con su propia nomenclatura de los nodos y las capas de enlaces.
- Tenga en cuenta que el campo P2013 puede almacenar cualquier cosa, por ejemplo, el número de arrendatarios o la superficie de la parcela. Si es así, puede agrupar los polígonos para mantener un número aproximadamente igual de personas, etc.
0 votos
¿Ha estudiado el análisis de asignación de lugares? help.arcgis.com/es/arcgisdesktop/10.0/help/index.html#/
0 votos
¿Ha probado el análisis de agrupación (estadística espacial)?
0 votos
También he publicado un pseudocódigo del procedimiento real que estoy utilizando, a ver si puede ayudar gis.stackexchange.com/questions/123289/
0 votos
@crmackey Agradezco el enlace a mi respuesta, pero no estoy seguro de cómo se podría ajustar el código enlazado (división de polígonos) para que se ajuste a este problema (agrupación de polígonos).