Оригінальний набір:
Створіть його псевдокопію (CNTRL-перетягування в TOC) і зробіть просторовим приєднанням один до багатьох з клоном. У цьому випадку я використовував відстань 500м. Вихідна таблиця:
Видаліть записи з цієї таблиці, де PAR_ID = PAR_ID_1 - просто.
Ітерація через таблицю та видалення записів, де (PAR_ID, PAR_ID_1) = (PAR_ID_1, PAR_ID) будь-якого запису над нею. Не так просто, використовуйте acrpy.
Обчисліть центроїди водозбору (UniqID = PAR_ID). Вони є вузлами або мережею. З'єднайте їх лініями за допомогою просторової таблиці приєднання. Ця окрема тема, безумовно, висвітлена десь на цьому форумі.
Сценарій нижче передбачає, що таблиця вузлів виглядає так:
де MUID прийшов з посилок, P2013 - поле для підбиття підсумків. У цьому випадку = 1 лише для підрахунку. [rcvnode] - вихід скрипта для зберігання ідентифікатора групи, рівного 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 і т.д. таблиці ваших вузлів (сортування?) Дивіться перші 3 групи у прикладі виведення. Це допомагає уникнути «зрізання гілок» при кожній наступній ітерації.
Настроювання сценарію для роботи з mxd:
- вам не потрібно імпортувати COMMON. Це моя власна річ, яка читає власну таблицю оточення, де вказані theNodesLayer, theLinksLayer, linksFromI, linksToI. Замініть відповідні рядки власним називанням вузлів та шарів посилань.
- Зауважте, що поле P2013 може зберігати будь-що, наприклад кількість орендарів або ділянку посилки. Якщо це так, ви можете згрупувати багатокутники, щоб вмістити приблизно рівну кількість людей тощо.