วิธีที่เร็วที่สุดสำหรับการปรับเปลี่ยนตารางแอตทริบิวต์ด้วย Python?


12

เมื่อไม่นานมานี้ฉันได้เขียนฟังก์ชั่น Python อย่างรวดเร็วสำหรับการแปลงตารางแอททริบิวไปเป็นพจนานุกรมไพ ธ อนโดยที่คีย์นั้นนำมาจากฟิลด์ 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

มันใช้งานได้ดีสำหรับชุดข้อมูลที่มีขนาดค่อนข้างเล็ก แต่ฉันเพิ่งรันบนตารางที่มีแถวประมาณ 750,000 แถวและ 15 สาขา - ประมาณ 100MB ในฐานข้อมูลไฟล์ทางภูมิศาสตร์ ฟังก์ชั่นนี้ทำงานช้ากว่าที่ฉันคาดไว้มาก: ประมาณ 5-6 นาที (และนี่คือหลังจากคัดลอกตารางไปยังin_memoryพื้นที่ทำงาน) ฉันต้องการหาวิธีเพิ่มความเร็วในการแปลงเป็นพจนานุกรมหรือรับข้อมูลเชิงลึกเกี่ยวกับกลยุทธ์ที่ดีกว่าสำหรับการจัดการข้อมูลแอตทริบิวต์จำนวนมากโดยใช้ Python

UpdateCursors จะทำงานได้ไม่ดีสำหรับฉันเพราะเมื่อมีการเปลี่ยนแปลงแถวหนึ่งมันมีโอกาสที่จะทำให้เกิดการเปลี่ยนแปลงในหลาย ๆ แถว การวนซ้ำและประมวลผลทีละรายการนั้นยุ่งยากเกินไปสำหรับสิ่งที่ฉันต้องการ


2
ปัจจัยที่ จำกัด ในจำนวนที่คุณสามารถเพิ่มประสิทธิภาพสคริปต์ของคุณอาจเป็นระยะเวลาที่ใช้ในการทำซ้ำผ่านเคอร์เซอร์ของคุณ คุณเปรียบเทียบเวลาที่ใช้ในการทำซ้ำผ่านเคอร์เซอร์โดยไม่ต้องสร้างพจนานุกรมของคุณหรือไม่
Jason

2
@ Jason แสดงความคิดเห็นในบรรทัดจากsubdict = {}ถึงdel subdictทำให้เวลาในการประมวลผลประมาณ 10 วินาที
nmpeterson

คุณอาจรู้เพิ่มเติมเกี่ยวกับเรื่องนี้มากกว่าฉัน แต่สิ่งเดียวที่ฉันจะเสนอในแง่ของการเพิ่มประสิทธิภาพคือการดูว่าการโทรsubdict[field] = row[cursor_fields.index(field)]นั้นเร็วกว่าการโทรsubdict[field] = row.getValue(field)หรือไม่ ในสถานการณ์หลังคุณจะต้องดำเนินการหนึ่งขั้นตอน ... แม้ว่าความแตกต่างของประสิทธิภาพระหว่างการทำดัชนีสองรายการ ( cursor_fieldsและrow) และการใช้กระบวนการ 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

สิ่งนี้ถูกสับเปลี่ยนผ่านชั้นข้อมูลคุณลักษณะทางภูมิศาสตร์ฐานข้อมูล 218k ระเบียน 16 ไฟล์ใน 8 วินาทีในระบบของฉัน

แก้ไข: พยายามทดสอบที่เข้มงวดยิ่งขึ้น 518k บันทึกผ่านการเชื่อมต่อ SDE ระยะไกลที่มี 16 ฟิลด์รวมถึง OBJECTID และ Shape ทำงานที่ 32- บิต 11 วินาที :)


1
โปรดทราบว่าฉันทำkey_fieldฟิลด์แรกเพื่อที่ฉันจะต้องพึ่งพาการใช้เพื่อการอ้างอิงค่าของrow[0] key_fieldฉันยังมีการเปลี่ยนแปลงตัวแปรของคุณจะdict attdictdict เป็นคำหลักและหากไม่มีคำหลักนั้นฉันไม่สามารถใช้งานได้dict(zip())
blord-castillo

6
ฉลาด. นี่คือประเภทของงูหลามที่arcpy.daมีจุดมุ่งหมายเพื่อเปิดใช้งาน
Jason Scheirer

ความเข้าใจที่ยอดเยี่ยม ชอบวิธีการและมันช่วยได้จริงๆ
nmpeterson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.