オリジナルセット:
それの疑似コピー(TOCのCNTRLドラッグ)を作成し、クローンを使用して1対多に空間結合します。この場合、距離500mを使用しました。出力テーブル:
このテーブルから、PAR_ID = PAR_ID_1-簡単なレコードを削除します。
テーブルを反復処理し、その上のレコードの(PAR_ID、PAR_ID_1)=(PAR_ID_1、PAR_ID)であるレコードを削除します。それほど簡単ではありません。acrpyを使用してください。
集水重心を計算します(UniqID = PAR_ID)。それらはノードまたはネットワークです。空間結合テーブルを使用して、それらを線で接続します。これは、このフォーラムのどこかで必ず取り上げられている別のトピックです。
以下のスクリプトでは、ノードテーブルが次のようになっていると想定しています。
MUIDが小包に由来する場合、P2013は要約するフィールドです。この場合、カウントのみの場合= 1。[rcvnode]-定義されたグループ/クラスターの最初のノードのNODERECに等しいグループIDを格納するスクリプト出力。
重要なフィールドが強調表示されたテーブル構造をリンクします
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で考慮し、2つの近隣グループの[P2013]の合計を計算します。必要な比率が達成された場合、たとえば最初の反復で(6-1)/ 1、比率減少ターゲット、つまり4などが1まで続きます。開始点は非常に重要であるため、「終了」ノードが一番上にあることを確認してくださいノードテーブルの(ソート?)出力例の最初の3つのグループを参照してください。これは、次の反復ごとに「分岐切断」を回避するのに役立ちます。
mxdから機能するスクリプトのカスタマイズ:
- COMMONをインポートする必要はありません。theNodesLayer、theLinksLayer、linksFromI、linksToIが指定された自分の環境テーブルを読み取るのは私自身のものです。関連する行を独自のノードとリンク層の名前に置き換えます。
- フィールドP2013には、テナントの数や区画面積など、何でも格納できることに注意してください。もしそうなら、ポリゴンをクラスタリングして、ほぼ同じ数の人などを保持できます。