ArcPy를 사용하여 다각형을 * n * 개의 동일한 수의 그룹으로 나눕니 까?


10

저의 업무 중 하나는 소포를 그룹으로 나누는 것입니다. 이 그룹은 에이전트가 부동산 소유자와 대화하는 데 사용됩니다. 목표는 서로 가까이있는 소포를 그룹화하고 소포를 같은 숫자로 나누어 작업이 고르게 분포되도록하여 에이전트의 작업을 쉽게하는 것입니다. 에이전트의 수는 커플에서 10+로 변동될 수 있습니다.

현재이 작업을 수동으로 수행하지만 가능한 경우 프로세스를 자동화하고 싶습니다. 다양한 ArcGIS 도구를 살펴 보았지만 내 필요에 맞는 것은 없습니다. near_analysis다각형을 사용 하고 선택 하는 스크립트 (python에서)를 시도했지만 다소 무작위이며 반 정확한 결과를 얻는 데 영원히 걸리므로 처음부터 수동으로 모든 것을 수행 한 것보다 수정하는 데 시간이 더 걸립니다.

이 작업을 자동화하는 신뢰할 수있는 방법이 있습니까?

결과 예 (분할없이 노란색으로 표시) :

분할 소포


위치 할당 분석을 살펴 보셨습니까? help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/…
phloem

그룹화 분석 (공간 통계)을 사용해 보셨습니까?
FelixIP

또한 사용중인 실제 프로 시저의 의사 코드도 게시했습니다. gis.stackexchange.com/questions/123289/…에
FelixIP

@ crmackey 내 답변에 대한 링크에 감사하지만이 문제 (다각형 그룹화)에 맞게 링크 된 코드 (다각형 다각형)를 어떻게 조정할 수 있는지 잘 모르겠습니다.
phloem

답변:


4

오리지널 세트 :

여기에 이미지 설명을 입력하십시오

그것의 의사 복사 (TOC에서 CNTRL- 드래그)를 생성하고 클론과 일대 다 공간 결합을 만듭니다. 이 경우 거리 500m를 사용했습니다. 출력 테이블 :

여기에 이미지 설명을 입력하십시오

  1. 이 테이블에서 PAR_ID = PAR_ID_1-쉬운 레코드를 제거하십시오.

  2. 테이블을 반복하고 위의 레코드 중 (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에서 작동하는 스크립트 사용자 정의 :

  1. 가져 오기 COMMON이 필요하지 않습니다. NodesLayer, the LinksLayer, linksFromI, linksToI가 지정된 자체 환경 테이블을 읽는 것은 저의 일입니다. 관련 선을 사용자 고유의 노드 및 링크 계층 이름으로 바꿉니다.
  2. 필드 P2013은 테넌트 수 또는 소포 영역과 같은 항목을 저장할 수 있습니다. 그렇다면 대략 같은 수의 사람 등을 보유하도록 다각형을 묶을 수 있습니다.

실제로 노드와 링크 레이어는 시각적 인 것입니다. 정리 된 공간 결합 테이블은 시작 및 끝 노드가 이미 지정되어 있으므로 링크 테이블을 쉽게 대체 할 수 있습니다. Polygons 테이블은 Nodes 테이블로 쉽게 사용할 수 있습니다. ReceivingNode 필드를 추가하고 순차적 번호를 다시 '링크'[FromI] 및 [ToI]로 전송하십시오.
FelixIP

이것은 좋아 보인다. 답변 주셔서 감사합니다. 방법뿐만 아니라 그 이유를 더 설명 할 수 있습니까? 코드에 대한 의견은 엄청납니다.
Emil Brundage 2016 년

귀하의 질문에 대한 이전 의견에서 하이퍼 링크를 따르십시오. 이것이 '왜'의 의미인지에 대한 접근법을 설명하려고 노력했습니다. Q에 대한 답변을 게시 한 후 스크립트를 죽이려고 레코드 순서를 임의로 변경했기 때문에 노드 시작의 중요성에 대한 의견을 철회했습니다. 아무 일도 일어나지 않았지만 여전히 합리적인 결과를 낳았습니다.
FelixIP

공간 조인 테이블을 정리하려면 NETWORKX의 비 방향 그래프에서 에지 / 링크 [0,2]가 에지 [2,0]이므로 PAR_ID = PAR_ID_1을 삭제하면 충분합니다. 업데이트 된 스크립트를 게시해도 평판에 영향을
줄지

@EmilBrundage 살펴봐, 왜 질문 gis.stackexchange.com/questions/165057/…에
FelixIP

2

목표를 달성하려면 "그룹 분석"도구를 사용해야합니다. 이 도구는 @phloem이 지적한 "공간 통계"도구 상자의 훌륭한 도구입니다. 그러나 데이터와 문제에 맞게 도구를 미세 조정해야합니다. 나는 당신이 게시 한 것과 비슷한 시나리오를 만들고 목표에 가까운 응답을 얻었습니다.

힌트 : 도구를 실행할 때 ArcGIS 10.2를 사용하면 누락 된 파이썬 패키지 인 "six"에 대해 불평했습니다. 먼저 링크를 설치했는지 확인하십시오.

단계 :

  1. 고유 한 값을 유지하기 위해 다각형 클래스에 필드를 추가하십시오.
  2. 이름이 Short 인 다른 유형의 필드를 추가하십시오 (예 : "SameGroup").
  3. 모든 필드에 대해이 필드에 1을 할당하는 필드 계산기. 한 행을 2로 변경하십시오. 추가 된 필드

  4. "그룹 분석"도구 매개 변수를 다음과 같이 설정하십시오. 그룹 분석

필요에 따라 "인근 수"매개 변수를 변경하십시오.

결과 스냅 샷 :

샘플 입력 다각형

그룹 분석 결과


2
나는 이전에 그룹 분석을 조사했다. 그것은 공간을 다루지 만 내가 알 수있는 한 계산하지는 않습니다. 문서를 읽고, 예제를보고, 자체 테스트를 수행 한 경험은 모두 같은 수의 다각형으로 그룹화 할 수 없습니다.
Emil Brundage

왜 평등해야합니까 (에이전트를위한 코스 외)? 그러나 그 제약 조건을 추가하면 공간 관계를 기반으로 데이터를 클러스터링하는 이유는 무엇입니까!?
Farid Cheraghi

1
상사가 그렇게 말했기 때문입니다. 또한 여행 시간을 최소화하십시오.
Emil Brundage 2012 년

1

기본적으로 동일한 크기의 클러스터링 방법을 원하므로 웹에서이 키워드를 사용하여 검색 할 수 있습니다. 저에게는 stats.SE에 대한 좋은 답변이 있습니다. arcpy에 익숙하면 데이터와 함께 사용할 수 있습니다.

먼저 다각형 중심의 X와 Y를 계산해야합니다. 그런 다음 스크립트에이 좌표를 입력하고 .da 커서를 사용하여 속성 테이블을 업데이트 할 수 있습니다.


귀하가 제공하는 링크가 올바른 궤도에있는 것처럼 보이지만 기본적으로 이해할 수없는 언어로되어 있습니다. 스크립트의 경우 입력이 무엇인지 모르고 정확히 무슨 일이 일어나고 있는지 이해하기 위해 코딩을 해독 할 수 없습니다. 설명이 거의 없습니다.
Emil Brundage 2016 년

0

안녕하세요, 나는 전에 이것과 비슷한 문제가 있었지만, 나는 그것을 시작했지만 결코 다른 시작을 얻지 못했습니다.

입력 형태

입력 모양

입력 모양에서 망사를 만들 수 있다고 생각했습니다.

망사 당신이 입력 모양의 교차와 fishnet 다음 것

영역에 입력

그런 다음 새로 처리 된 다각형 내에서이 구획의 면적을 계산할 수 있습니다

스크립트 시작시 원하는 크기의 영역 입력 다각형 / n 번째 양

그런 다음 경계가있는 항목을 인식하도록 소포를 연결하는 방법이 필요합니다.

그런 다음 소포를 요약하는 행 커서를 통과 할 수 있습니다

되는 규칙

* 마지막 여름에 경계를 공유 * 합산되지 않음 * 같은 영역으로 계산 된 값을 넘어 서면 단계적으로 되돌아 가고 그룹이 됨 * 프로세스가 다시 시작됨 * 마지막 그룹이 될 수 있음 남은 소포의 합

나는 소포 사이의 관계를 수립하는 것이 까다로운 일이라고 생각하지만 일단 이것이 끝나면 자동화 할 수 있다고 생각합니다.


이것이 내 문제와 어떤 관련이 있는지 이해가되지 않습니다. 어망으로 다각형을 자르는 것은 다각형을 공간적으로 그리고 같은 수로 그룹화하는 것과 어떤 관련이 있습니까? 당신은 세지 않고 지역에 집중 한 것 같습니다. 구획 다각형의 면적 (크기)은 중요하지 않습니다. 소포의 크기에 상관없이 여전히 한 명의 부동산 소유자 만 이야기 할 수 있습니다. 빨간색이 시골 지역이고 넓게 퍼지는 반면, 주황색은 도시 지역이므로 전체 면적이 훨씬 더 작은 내 예를 참조하십시오.
Emil Brundage

안녕하세요, 죄송합니다. 질문을 잘못 읽었습니다. 나는 radouxju 게시물이 갈 수있는 방법이라고 생각하지만 링크가 내 머리 위로 조금 넘어갑니다. 다각형을 점으로 바꾸면 논리적으로 그룹화됩니다. 공간 요소를 정의 할 수있는 도로 및 다음 지점에 지점으로부터의 거리로 도로 시스템을 도입하는 방법이있을 수 있습니다
잭 워커


0

이것은 포인트 이벤트에 대한 나의 솔루션입니다. 항상 작동한다는 보장은 없습니다 ...

  1. 포인트 이벤트 레이어 (콜 레이어 1)에서 x (double), y (double) 및 uniqueid (long integer)에 대한 열을 추가합니다.
  2. 레이어 1의 속성 테이블을 엽니 다. x의 x 좌표 점, y의 y 좌표 점 및 고유 ID의 FID를 계산합니다.
  3. 공간 통계 도구 실행> 클러스터 매핑> 그룹화 분석
    • 입력 기능으로 layer1 설정
    • uniqueid를 고유 필드 ID로 설정
    • 그룹 수를 정의하십시오 (우리는 10이라고 말할 것입니다)
    • 분석 필드로 x와 y를 선택하십시오.
    • 공간 제약 조건으로 "NO_SPATIAL_CONSTRAINT"를 선택하십시오.
    • 확인을 클릭하십시오
  4. 공간 통계 도구 실행> 지리적 분포 측정> 평균 센터
    • 입력 기능 클래스로 # 3의 출력을 선택하십시오.
    • 케이스 필드로 SS_Group을 선택하십시오.
    • 확인을 클릭하십시오
  5. 개방형 네트워크 분석가> 위치 할당 도구
    • 설비로서 # 4의 부하 출력
    • 수요 지점으로 layer1로드
    • 속성 열기 및 설정
      • 정전 용량 범위를 최대화하는 문제 유형
      • 10으로 선택할 수있는 시설 (위 3 번)
      • 계층 1의 총 기능 수를 반올림 할 시설로 나눈 기본 용량 (145 개의 기능 및 10 개의 시설 / 지역이 15로 설정된 경우)
      • 확인을 클릭하십시오
        • 풀다
        • 수요 지점은 10 개의 지리적 클러스터로 거의 동일하게 분산되어야합니다.

나는 당신의 방법의 5 단계에 붙어 있습니다. Network Analyst 확장을 확인하고 Network Analyst 도구 모음을 추가했습니다. 그러나 대부분은 회색으로 표시되며 "위치 할당 도구"가 표시되지 않습니다. 10.1을 사용하고 있습니다.
Emil Brundage 2016 년

0

먼저 거리를 사용하여 네트워크 데이터 세트를 만들어야합니다. 나는이 제안 된 방법을 시도해 왔고 지금까지 입력 필드에 X, Y 좌표와 k- 평균을 사용하여 그룹화 (3 단계)와 같은 일을하는 것이 더 좋았습니다. 필요). 나는 다른 사람들의 의견과 피드백에 열려 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.