파이썬으로 속성 테이블을 수정하는 가장 빠른 방법?


12

얼마 전, 속성 테이블을 파이썬 사전으로 변환하는 빠른 파이썬 함수를 작성했습니다.이 키는 사용자 지정 고유 ID 필드 (일반적으로 OID 필드)에서 가져옵니다. 또한 기본적으로 모든 필드가 사전에 복사되지만 하위 집합 만 지정할 수있는 매개 변수가 포함되었습니다.

def make_attribute_dict(fc, key_field, attr_list=['*']):
    dict = {}
    fc_field_objects = arcpy.ListFields(fc)
    fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
    if attr_list == ['*']:
        valid_fields = fc_fields
    else:
        valid_fields = [field for field in attr_list if field in fc_fields]
    if key_field not in valid_fields:
        cursor_fields = valid_fields + [key_field]
    else:
        cursor_fields = valid_fields
    with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
        for row in cursor:
            key = row[cursor_fields.index(key_field)]
            subdict = {}
            for field in valid_fields:
                subdict[field] = row[cursor_fields.index(field)]
            dict[key] = subdict
            del subdict
    return dict

이것은 상대적으로 작은 데이터 세트에 효과적이지만 파일 지오 데이터베이스에서 약 100MB의 약 750,000 개의 행과 15 개의 필드를 포함하는 테이블에서 실행했습니다. 이것들에서, 함수는 내가 예상했던 것보다 훨씬 느리게 실행됩니다 : 약 5-6 분 (그리고 이것은 테이블을 in_memory작업 공간에 복사 한 후입니다 ). 사전으로의 변환 속도를 높이거나 Python을 사용하여 많은 양의 속성 데이터를 조작하기위한 더 나은 전략에 대한 통찰력을 얻고 싶습니다.

한 행이 변경되면 다른 행에서 변경 사항을 트리거 할 가능성이 있기 때문에 UpdateCursors는 나에게 잘 작동하지 않습니다. 한 번에 하나씩 반복하여 처리하는 것은 내가 필요한 것에 너무 성가시다.


2
스크립트를 얼마나 많이 최적화 할 수 있는지에 대한 제한 요인은 커서를 반복하는 데 걸리는 시간 일 수 있습니다. 사전을 작성하지 않고 커서를 반복하는 데 걸리는 시간을 비교 했습니까?
Jason

2
@Jason은 라인을 subdict = {}통해 주석 del subdict처리를하여 약 10 초의 처리 시간 을 산출합니다.
nmpeterson

아마도 나보다 이것에 대해 더 많이 알고 있지만 최적화 측면에서 내가 제공 할 수있는 유일한 것은 호출 subdict[field] = row[cursor_fields.index(field)]이 calling 보다 빠른지 여부를 보는 것 subdict[field] = row.getValue(field)입니다. 후자의 시나리오에서는 두 단계 ( cursor_fieldsrow)를 인덱싱 하고 단일 ESRI 프로세스를 사용하는 것의 성능 차이 가 훨씬 나아지지 않을 수도 있지만 한 단계 만 수행하는 것입니다 !
Jason

답변:


16

문제는 필드를 통해 각 필드를 개별적으로 subdict사전에 추가하는 두 줄 입니다.

for field in valid_fields:
    subdict[field] = row[cursor_fields.index(field)]

당신의 row목적은 그 활용과 사용, 이미 필드와 같은 순서로 튜플입니다 zip기능을.

def make_attribute_dict(fc, key_field, attr_list=['*']):
    attdict = {}
    fc_field_objects = arcpy.ListFields(fc)
    fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
    if attr_list == ['*']:
        valid_fields = fc_fields
    else:
        valid_fields = [field for field in attr_list if field in fc_fields]
    #Ensure that key_field is always the first field in the field list
    cursor_fields = [key_field] + list(set(valid_fields) - set([key_field]))
    with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
        for row in cursor:
            attdict[row[0]] = dict(zip(cursor.fields,row))
    return attdict

이것은 내 시스템에서 8 초 만에 218k 레코드 16 필드 파일 지오 데이터베이스 기능 클래스를 통과했습니다.

편집 : 더 엄격한 테스트를 시도했습니다. 518k는 32 ​​비트에서 실행되는 OBJECTID 및 Shape를 포함한 16 개의 필드로 원격 SDE 연결을 통해 기록합니다. 11 초 :)


1
의 값을 참조하는 데 key_field사용할 수 있도록 첫 번째 필드를 만들었습니다 . 또한 변수 를 로 변경해야 했습니다 . dict는 키워드이며 해당 키워드가 없으면 사용할 수 없습니다row[0]key_fielddictattdictdict(zip())
blord-castillo

6
영리한. 이것은 정확히 사용 가능한 달콤한 관용적 파이썬입니다 arcpy.da.
Jason Scheirer 2016 년

훌륭한 통찰력. 방법을 좋아하고 실제로 도움이되었습니다.
nmpeterson 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.