Conjunto original:
Crie uma pseudo-cópia (arraste CNTRL no sumário) e faça a junção espacial de uma para muitas com o clone. Neste caso, usei a distância 500m. Tabela de saída:
Remova os registros desta tabela onde PAR_ID = PAR_ID_1 - fácil.
Itere a tabela e remova os registros em que (PAR_ID, PAR_ID_1) = (PAR_ID_1, PAR_ID) de qualquer registro acima dela. Não é tão fácil, use acrpy.
Calcular centróides de captação (UniqID = PAR_ID). Eles são nós ou rede. Conecte-os por linhas usando a tabela de junção espacial. Este é um tópico separado, certamente coberto em algum lugar deste fórum.
O script abaixo assume que a tabela de nós se parece com isso:
de onde o MUID veio das parcelas, o P2013 é um campo para resumir. Neste caso = 1 apenas para contagem. [rcvnode] - saída de script para armazenar o ID do grupo igual a NODEREC do primeiro nó no grupo / cluster definido.
Liga a estrutura da tabela com os campos importantes destacados
O Times armazena o peso do link / borda, ou seja, o custo da viagem de um nó para outro. Igual a 1 neste caso, para que o custo da viagem para todos os vizinhos seja o mesmo. [fi] e [ti] são um número seqüencial de nós conectados. Para preencher esta tabela, pesquise neste fórum sobre como atribuir de e para nós ao link.
Script personalizado para meu próprio ambiente de trabalho mxd. Tem que ser modificado, codificado permanentemente com a nomeação dos campos e fontes:
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)
ENCONTRE A CAMADA DE NODES
theNodesLayer = COMMON.getInfoFromTable(theT,1)
theNodesLayer = COMMON.isLayerExist(mxd,theNodesLayer)
GET LINKS LAYER
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()
Exemplo de saída para 6 grupos:
Você precisará do pacote do site NETWORKX
http://networkx.github.io/documentation/development/install.html
O script usa o número necessário de clusters como parâmetro (6 no exemplo acima). Ele está usando tabelas de nós e links para criar um gráfico com peso / distância iguais das arestas de deslocamento (Times = 1). Ele considera a combinação de todos os nós por 2 e calcula o total de [P2013] em dois grupos de vizinhos. Quando a taxa necessária alcançada, por exemplo, (6-1) / 1 na primeira iteração, continua com a meta de taxa reduzida, ou seja, 4, etc. até 1. Os pontos de partida são de grande importância, portanto, verifique se os nós 'finais' estão no topo da tabela de nós (classificando?) Veja os 3 primeiros grupos na saída de exemplo. Isso ajuda a evitar o 'corte de ramificação' a cada próxima iteração.
Customização de script para trabalhar no mxd:
- você não precisa importar COMUM. É minha coisa, que lê minha própria tabela de ambiente, onde theNodesLayer, theLinksLayer, linksFromI, linksToI especificado. Substitua as linhas relevantes por sua própria nomeação de nós e camadas de links.
- Observe que o campo P2013 pode armazenar qualquer coisa, por exemplo, número de inquilinos ou área de encomendas. Nesse caso, você pode agrupar polígonos para conter aproximadamente o mesmo número de pessoas, etc.