ArcPy 스크립트가 느린 이유는 무엇입니까?


12

점 모양 파일의 필드를 그 안에있는 다각형 기능의 정보로 업데이트하는 간단한 arcpy 스크립트가 있습니다. arcpy에서 100 포인트를 수행하는 데 9 분이 걸리지 만 arcmap의 공간 결합은 즉각적입니다. 이 문제를 해결할 수있는 빠른 방법이 확실합니다. 누군가 올바른 방향으로 나를 가리킬 수 있습니까?

import took 0:00:07.085000
extent took 0:00:05.991000
one pt loop took 0:00:03.780000
one pt loop took 0:00:03.850000
one pt loop took 0:00:03.791000


import datetime
t1 = datetime.datetime.now()
import arcpy
t2 = datetime.datetime.now()
print "import took %s" %  ( t2-t1)
#set up environment
arcpy.env.workspace = "data\\"
arcpy.env.overwriteOutput = True

desc = arcpy.Describe("parcels.shp")
ext = desc.Extent
extent = (ext.XMin,ext.XMax,ext.YMin,ext.YMax)
t3 = datetime.datetime.now()
print "extent took %s" %  (t3 -t2)
fc = arcpy.CreateRandomPoints_management("", "malls.shp", "", ext, 100, "", "POINT", "")
arcpy.AddField_management("malls.shp", 'ParcelID', 'LONG')

rows = arcpy.UpdateCursor('malls.shp',"","",'ParcelID')
for row in rows:
    t4 = datetime.datetime.now()
    pt = row.Shape.getPart()
    for polyrow in arcpy.SearchCursor('parcels.shp'):
        t6 = datetime.datetime.now()
        poly = polyrow.getValue('Shape')
        if extent[0]<pt.X<extent[1] and extent[2]<pt.Y<extent[3]:
            if poly.contains(pt):
                print "works"
                row.ParcelID = polyrow.Parcels_ID
                rows.updateRow(row)
                break #we can stop looking for matches since
        t7 = datetime.datetime.now()
        "a full poly loop took %s" % (t7-t6)
    t5 = datetime.datetime.now()
    print "one pt loop took %s" % (t5-t4)


print datetime.datetime.now() -t1

4
현재 어떤 ArcGIS 버전이 있습니까? 10.1 arcpy.da은 커서가 훨씬 빠른 버전의 (데이터 액세스) 모듈을 추가했습니다 .
blah238

답변:


20

에 대한 두 번째 커서를 작성해야하는 경우 parcels.shp첫 번째 커서의 루프 외부에서 작성하십시오. 그대로, 스크립트는 각 행에 대해 새 커서 객체를 생성하므로 malls.shp처리 시간이 많이 걸립니다.

...
rows = arcpy.UpdateCursor('malls.shp',"","",'ParcelID')
polyrows = arcpy.SearchCursor('parcels.shp')
for row in rows:
    t4 = datetime.datetime.now()
    pt = row.Shape.getPart()
    for polyrow in polyrows:
...

바로 그거야. 감사합니다. 그런 다음 횡단 할 때마다 두 번째 커서에서 .reset ()을 사용합니까? 커서를 한 번만 통과하는 것처럼 보입니다.
EmdyP

흠, 당신은 행을 재설정 할 필요가 없습니다. 스크립트 끝에서 행 객체와 커서 객체를 모두 삭제해야합니다. 당신이하지 않으면 재미있는 일이 발생할 수 있습니다.
Jason

나는 내부 루프의 커서가 생각 하지 않습니다 이 경로를 이동하는 경우 매번 다시 설정해야합니다. 대안에 대한 내 대답을 참조하십시오.
blah238

10

의 문제 의 제이슨 @ 답 (그리고 원래의 접근 방식은)는 공간 인덱스를 활용하지 않는다는 것입니다 포인트의 수가 증가함에 따라 기하 급수적으로 느려질 것입니다 중첩 된 두 개의 커서 루프를 필요로한다.

포인트 피쳐 클래스를 제자리에서 계속 업데이트 할 수 있지만 더 빠른 대체 워크 플로우 (공간 결합은 기존 피쳐 클래스를 업데이트하지 않고 새 피쳐 클래스 만 출력 함)는 다음과 같습니다.

  1. 사용 공간은 가입 중간 (아마도 메모리) 기능 클래스를 만들
  2. 조인 추가를 사용 하여 중간 피쳐 클래스를 기존 포인트 피쳐 클래스에 결합
  3. 필드 계산 또는 UpdateCursor 를 사용 하여 조인 된 필드의 값을 기존 점 피쳐 클래스의 필드로 복사합니다.

2
이 대안 워크 플로가 마음에 듭니다. 질문을하지 않아도 여기서도 새로운 방법을 배우고 있습니다.
Jason
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.