200k 다각형의 1 차 이웃을 효율적으로 찾기


14

208,781 인구 조사 블록 그룹 중 하나에 대해 모든 1 차 이웃의 FIPS ID를 검색하고 싶습니다. 모든 TIGER 경계를 다운로드하여 단일 1GB shapefile로 병합했습니다.

코어에서 BOUNDARY_TOUCHES에 SelectLayerByLocation을 사용하는 ArcPython 스크립트를 사용해 보았지만 각 블록 그룹에 대해 1 초 이상 걸리고 싶습니다. 이것은 SelectLayerByLocation 검색을 동일한 상태의 그룹을 차단하도록 제한 한 후에도 가능합니다. 이 스크립트를 찾았 지만 내부적으로 SelectLayerByLocation을 사용하므로 더 빠르지 않습니다.

이 솔루션은 Arc 기반 일 필요는 없습니다. Python으로 코딩하는 것이 가장 편하지만 다른 패키지를 사용할 수 있습니다.


2
버전 9.3 이후, 공간 통계 도구 상자에이를 수행하기위한 도구가 있습니다. 10.0부터는 매우 효율적입니다. 필자는 비슷한 크기의 셰이프 파일 ( 한 상태의 모든 블록) 에서 비슷한 작업을 실행 한 것을 기억 하고 30 분 만에 디스크 I / O에 대한 것 중 15 분 안에 완료했습니다. 이는 2 년 전 훨씬 느린 컴퓨터에서 수행되었습니다. 파이썬 소스 코드에도 접근 할 수 있습니다.
whuber

공간 통계에서 어떤 지오 프로세싱 도구를 사용 했습니까?
dmahr

1
나는 그 이름을 잊었다. 특히 폴리곤 이웃 관계 테이블을 만들기위한 것입니다. 도움말 시스템 은 이웃 기반 공간 통계 도구 실행 하기 전에이 테이블을 작성 하여 도구가 실행될 때마다이 정보를 즉시 다시 계산하지 않아도되도록 권장합니다 . 적어도 9.x 버전에서 중요한 제한 사항은 출력이 .dbf 형식이라는 것이 었습니다. 작동하지 않는 큰 입력 셰이프 파일의 경우 작업을 여러 조각으로 나누거나 Python 코드를 해킹하여 더 나은 형식으로 출력해야합니다.
whuber


그래 그거야. Python 코드는 공간 인덱스를 사용하는 내부 ArcGIS 기능을 완전히 활용하여 알고리즘을 매우 빠르게 만듭니다.
whuber

답변:


3

데스크탑 용 ArcGIS 10.2 또는 그 이전 버전에 액세스 할 수있는 경우 다음과 같은 Polygon Neighbors (Analysis) 도구를 생각합니다 .

다각형 연속성 (중복, 일치 모서리 또는 노드)을 기반으로 통계가 포함 된 테이블을 만듭니다.

다각형 이웃

이 작업을 훨씬 쉽게 할 수 있습니다.


고마워, PolyGeo. Polygon Neighbors 도구가 조금 더 노출되도록 허용되는 답변을 업데이트했습니다. 큰 데이터 세트의 확장 성이 어떻게 비교되는지 확실하지 않지만 수동 Python 기반 방법보다 확실히 강력합니다.
dmahr

현재 10.3을 사용하고 있으며 ~ 300K의 센서스 블록으로 shapefile에서 실패합니다.
soandos

@soandos 그것은 새로운 질문으로 연구 / 질문 할 가치가있는 것 같습니다.
PolyGeo

8

ArcGIS를 피하기 위해 pysal을 사용 하십시오 . 다음을 사용하여 shapefile에서 직접 가중치를 얻을 수 있습니다.

w = pysal.rook_from_shapefile("../pysal/examples/columbus.shp")

또는

w = pysal.queen_from_shapefile("../pysal/examples/columbus.shp")

이용 헤드 워드 프로세서 추가 정보를 원하시면.


3

그냥 업데이트. Whuber의 조언을 따르면, 공간 가중치 생성 매트릭스는 단순히 파이썬 루프와 사전을 사용하여 이웃을 결정한다는 것을 알았습니다. 아래 과정을 재현했습니다.

첫 번째 부분은 모든 블록 그룹의 모든 정점을 반복합니다. 키로 정점 좌표가있는 사전과 해당 좌표에 정점이 값으로있는 블록 그룹 ID 목록을 만듭니다. 완벽한 정점 / 정점 겹침 만 인접 관계로 등록되므로 위상 적으로 깔끔한 데이터 세트가 필요합니다. 다행히도 인구 조사국의 TIGER 블록 그룹 형태 파일은 이와 관련하여 문제가 없습니다.

두 번째 부분은 모든 블록 그룹의 모든 정점을 다시 반복합니다. 블록 그룹 ID를 키로 사용하고 해당 블록 그룹의 인접 ID를 값으로 사용하여 사전을 작성합니다.

# Create dictionary of vertex coordinate : [...,IDs,...]
BlockGroupVertexDictionary = {}
BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp)
BlockGroupDescription = arcpy.Describe(BlockGroups.shp)
BlockGroupShapeFieldName = BlockGroupsDescription.ShapeFieldName
#For every block group...
for BlockGroupItem in BlockGroupCursor :
    BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00")
    BlockGroupFeature = BlockGroupItem.getValue(BlockGroupShapeFieldName)
    for BlockGroupPart in BlockGroupFeature:
        #For every vertex...
        for BlockGroupPoint in BlockGroupPart:
            #If it exists (and isnt empty interior hole signifier)...
            if BlockGroupPoint:
                #Create string version of coordinate
                PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y)
                #If coordinate is already in dictionary, append this BG's ID
                if PointText in BlockGroupVertexDictionary:
                    BlockGroupVertexDictionary[PointText].append(BlockGroupID)
                #If coordinate is not already in dictionary, create new list with this BG's ID
                else:
                    BlockGroupVertexDictionary[PointText] = [BlockGroupID]
del BlockGroupItem
del BlockGroupCursor


#Create dictionary of ID : [...,neighbors,...]
BlockGroupNeighborDictionary = {}
BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp)
BlockGroupDescription = arcpy.Describe(BlockGroups.shp)
BlockGroupShapeFieldName = BlockGroupDescription.ShapeFieldName
#For every block group
for BlockGroupItem in BlockGroupCursor:
    ListOfBlockGroupNeighbors = []
    BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00")
    BlockGroupFeature = BlockGroupItem.getValue(BlockGroupShapeFieldName)
    for BlockGroupPart in BlockGroupFeature:
        #For every vertex
        for BlockGroupPoint in BlockGroupPart:
            #If it exists (and isnt interior hole signifier)...
            if BlockGroupPoint:
                #Create string version of coordinate
                PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y)
                if PointText in BlockGroupVertexDictionary:
                    #Get list of block groups that have this point as a vertex
                    NeighborIDList = BlockGroupVertexDictionary[PointText]
                    for NeighborID in NeighborIDList:
                        #Don't add if this BG already in list of neighbors
                        if NeighborID in ListOfBGNeighbors:
                            pass
                        #Add to list of neighbors (as long as its not itself)
                        elif NeighborID != BlockGroupID:
                            ListOfBGNeighbors.append(NeighborID)
    #Store list of neighbors in blockgroup object in dictionary
    BlockGroupNeighborDictionary[BlockGroupID] = ListOfBGNeighbors

del BlockGroupItem
del BlockGroupCursor
del BlockGroupVertexDictionary

후시로, 나는 shapefile을 다시 반복 할 필요가없는 두 번째 부분에 대해 다른 방법을 사용할 수 있음을 알고 있습니다. 그러나 이것은 내가 사용한 것이며 한 번에 1000 개의 블록 그룹에서도 잘 작동합니다. 나는 미국 전체에서 시도하지는 않았지만 전체 국가에서 실행할 수 있습니다.


2

대안은 PostgreSQL 및 PostGIS 를 사용하는 것 입니다. 이 사이트에서 유사한 계산을 수행하는 방법에 대한 몇 가지 질문을했습니다.

다양한 소프트웨어가 어떻게 결합되는지 알아내는 데 가파른 학습 곡선이 있다는 것을 알았지 만 큰 벡터 레이어에서 계산하는 것이 훌륭하다는 것을 알았습니다. 수백만 개의 다각형에서 가장 가까운 이웃 계산을 실행했으며 ArcGIS와 비교했을 때 빠릅니다.


1

esri / ArcGIS 메소드는 현재 사전을 사용하여 정보를 보유하지만 핵심 계산은 Polygon Neighbors Tool을 사용하여 C ++로 수행됩니다. 이 도구는 연속 경계 정보 및 공유 경계 길이와 같은 선택적 속성을 포함하는 테이블을 생성합니다. 정보를 저장 한 다음 계속해서 재사용하려는 경우 공간 가중치 생성 매트릭스 도구를 사용할 수 있습니다. 또한 WeightsUtilities에서이 기능을 사용하여 연속성 정보가 포함 된 사전 [임의 액세스]을 생성 할 수 있습니다.

contDict = polygonNeighborDict(inputFC, masterField, contiguityType = "ROOK")

여기서 inputFC = 모든 유형의 다각형 피쳐 클래스 인 masterField는 { "ROOK", "QUEEN"}에서 정수 및 contiguityType의 "고유 ID"필드입니다.

esri는 Python 사용자의 표 형식을 건너 뛰고 많은 사용 사례를 훨씬 빠르게 만드는 반복기로 직접 이동하려는 노력이 있습니다. R의 PySAL과 spdep 패키지는 환상적인 대안입니다 [ radek 's answer] . 이 스레드 입력 형식과 함께 조정되는이 패키지의 데이터 형식으로 shapefile을 사용해야한다고 생각합니다. 겹치는 다각형과 다각형 내의 다각형을 어떻게 처리하는지 잘 모르겠습니다. SWM을 생성 할뿐만 아니라 설명 된 함수는 공간 관계를 "ROOK"및 "QUEEN"이웃으로 계산합니다.

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