原始集:
创建它的伪副本(在TOC中拖动CNTRL),并使用克隆使空间连接一对多。在这种情况下,我使用距离500m。输出表:
从此表中删除PAR_ID = PAR_ID_1的记录-很容易。
遍历表并删除记录,其中上面的任何记录的(PAR_ID,PAR_ID_1)=(PAR_ID_1,PAR_ID)。不太容易,请使用acrpy。
计算流域质心(UniqID = PAR_ID)。它们是节点或网络。使用空间连接表通过线连接它们。这是必定涵盖在该论坛某个位置的单独主题。
下面的脚本假定节点表如下所示:
MUID来自地块,P2013是总结的领域。在这种情况下,= 1仅用于计数。[rcvnode]-脚本输出,用于在定义的组/集群中存储等于第一个节点的组ID NODEREC。
链接表结构并突出显示重要字段
时间存储链接/边缘权重,即从节点到节点的旅行成本。在这种情况下,等于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)。它使用节点和链接表来制作具有相等权重/距离的行进边缘(时间= 1)的图形。它考虑所有节点的组合为2,并计算两组邻居的[P2013]总数。当达到所需比率时,例如第一次迭代时达到(6-1)/ 1,则继续降低比率目标,即4,依此类推,直到1。起点非常重要,因此请确保您的“末端”节点位于顶部您的节点表(排序?)请参见示例输出中的前3组。它有助于避免在每次下一次迭代时进行“分支切割”。
脚本自定义可从mxd运行:
- 您不需要导入COMMON。是我自己的事情,它读取我自己的环境表,其中指定了NodesLayer,theLinksLayer,linksFromI,linksToI。用您自己的节点和链接层命名替换相关行。
- 请注意,字段P2013可以存储任何内容,例如租户数或宗地面积。如果是这样,您可能会聚簇多边形以容纳大约相等数量的人等。