오리지널 세트 :
그것의 의사 복사 (TOC에서 CNTRL- 드래그)를 생성하고 클론과 일대 다 공간 결합을 만듭니다. 이 경우 거리 500m를 사용했습니다. 출력 테이블 :
이 테이블에서 PAR_ID = PAR_ID_1-쉬운 레코드를 제거하십시오.
테이블을 반복하고 위의 레코드 중 (PAR_ID, PAR_ID_1) = (PAR_ID_1, PAR_ID) 인 레코드를 제거하십시오. 그렇게 쉬운 일은 아닙니다.
집수 중심을 계산합니다 (UniqID = PAR_ID). 이들은 노드 또는 네트워크입니다. 공간 조인 테이블을 사용하여 선으로 연결하십시오. 이것은이 포럼 어딘가에서 확실히 다루어 진 별도의 주제입니다.
아래 스크립트는 노드 테이블이 다음과 같다고 가정합니다.
MUID가 소포에서 나온 경우 P2013은 요약 할 필드입니다. 이 경우 계수에만 1 = 1입니다. [rcvnode]-정의 된 그룹 / 클러스터에서 첫 번째 노드의 그룹 ID와 동일한 NODEREC을 저장하는 스크립트 출력.
중요 필드가 강조 표시된 테이블 구조 연결
Times는 링크 / 에지 가중치, 즉 노드 간 이동 비용을 저장합니다. 이 경우에 1은 모든 이웃에 대한 여행 비용이 동일하도록합니다. [fi] 및 [ti]는 연속 된 수의 연결된 노드이다. 이 테이블을 채우려면 링크 할 노드에 할당하는 방법에 대해이 포럼을 검색하십시오.
내 워크 벤치 mxd에 맞게 사용자 정의 된 스크립트. 필드 및 소스 이름을 지정하여 수정하고 하드 코딩해야합니다.
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)
노드 찾기
theNodesLayer = COMMON.getInfoFromTable(theT,1)
theNodesLayer = COMMON.isLayerExist(mxd,theNodesLayer)
링크 레이어 얻기
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()
6 개 그룹의 출력 예 :
NETWORKX http://networkx.github.io/documentation/development/install.html 사이트 패키지가 필요합니다.
스크립트는 필요한 수의 클러스터를 매개 변수로 사용합니다 (위의 예에서 6). 이동 에지의 무게 / 거리가 동일한 그래프를 만들기 위해 노드와 링크 테이블을 사용하고 있습니다 (Times = 1). 모든 노드의 조합을 2 씩 고려하고 두 그룹의 이웃에서 총 [P2013]을 계산합니다. 첫 번째 반복에서 (6-1) / 1과 같이 필요한 비율이 달성되면 비율 목표, 즉 4 등을 1까지 줄입니다. 시작점이 매우 중요하므로 '끝'노드가 맨 위에 있어야합니다. 노드 테이블 (정렬?) 예제 출력의 처음 3 개 그룹을 참조하십시오. 매번 반복 할 때마다 '분기 절단'을 피하는 데 도움이됩니다.
mxd에서 작동하는 스크립트 사용자 정의 :
- 가져 오기 COMMON이 필요하지 않습니다. NodesLayer, the LinksLayer, linksFromI, linksToI가 지정된 자체 환경 테이블을 읽는 것은 저의 일입니다. 관련 선을 사용자 고유의 노드 및 링크 계층 이름으로 바꿉니다.
- 필드 P2013은 테넌트 수 또는 소포 영역과 같은 항목을 저장할 수 있습니다. 그렇다면 대략 같은 수의 사람 등을 보유하도록 다각형을 묶을 수 있습니다.