เลือกระเบียนที่เกี่ยวข้องอย่างมีประสิทธิภาพโดยใช้ ArcPy?


14

ด้านล่างเป็นรหัสที่ฉันใช้เพื่อทำซ้ำปุ่ม "ตารางที่เกี่ยวข้อง" ใน ArcMap ใน ArcMap ปุ่มนั้นจะเลือกคุณสมบัติในคลาสหรือตารางคุณลักษณะหนึ่งโดยยึดตามการเลือกคุณสมบัติในคลาสหรือตารางคุณสมบัติอื่นที่เกี่ยวข้อง

ใน ArcMap ฉันสามารถใช้ปุ่มนั้นเพื่อ "ดัน" การเลือกของฉันไปยังตารางที่เกี่ยวข้องในไม่กี่วินาที ฉันไม่สามารถค้นหาสิ่งใด ๆ ที่อยู่ใน arcpy ที่ทำซ้ำปุ่มดังนั้นฉันจึงใช้ลูปซ้อนกันเพื่อทำงานเดียวกัน

รหัสด้านล่างวนผ่านตารางของ "การรักษา" สำหรับการรักษาแต่ละครั้งมันจะวนรอบรายการของ "ต้นไม้" เมื่อพบคู่ที่ตรงกันระหว่างฟิลด์ ID ของการรักษาและต้นไม้การเลือกจะเกิดขึ้นในเลเยอร์ต้นไม้ เมื่อพบการจับคู่สำหรับการรักษารหัสจะไม่ดำเนินการค้นหาเลเยอร์ต้นไม้สำหรับการแข่งขันเพิ่มเติม มันจะกลับไปที่ตารางการรักษาเลือกการรักษาถัดไปและค้นหาอีกครั้งผ่านคลาสคุณลักษณะทรี

โค้ดนั้นใช้งานได้ดี แต่มันช้ามาก "ตารางการรักษา" ในกรณีนี้มี 16,000 บันทึก คลาสคุณลักษณะ "tree" มี 60,000 รายการ

มีวิธีอื่นที่มีประสิทธิภาพมากกว่าในการสร้างสิ่งที่ ESRI ทำเมื่อผลักการเลือกจากตารางหนึ่งไปยังอีกตารางหนึ่งหรือไม่ ฉันควรสร้างดัชนีสำหรับตารางหรือไม่ หมายเหตุ: ข้อมูลนี้ถูกเก็บไว้ใน SDE

 # Create search cursor to loop through the treatments
treatments = arcpy.SearchCursor(treatment_tv)
treatment_field = "Facility_ID"

for treatment in treatments:

    #Get ID of treatment
    treatment_ID = treatment.getValue(treatment_field)

    # Create search cursor for looping through the trees
    trees = arcpy.SearchCursor(tree_fl)
    tree_field = "FACILITYID"

    for tree in trees:

        # Get FID of tree
        tree_FID = tree.getValue(tree_field)

        if tree_FID == treatment_FID:
            query = "FACILITYID = " + str(tree_FID)
            arcpy.SelectLayerByAttribute_management(tree_fl, "REMOVE_FROM_SELECTION", query)
            break

2
คุณใช้ ArcGIS 10.1 หรือไม่ ถ้าเป็นเช่นนั้น arcpy.da.SearchCursor น่าจะเร็วกว่า (อาจเป็น 10 เท่า) กว่า arcpy.SearchCursor นอกจากนี้คุณอาจต้องการใช้พจนานุกรม Python ฉันสงสัยว่า "การเลือกไฟล์คีย์" เช่นนี้อาจได้รับประโยชน์อย่างมากจากวิธีการที่ใช้ที่นี่
PolyGeo

ฐานข้อมูล SDE ของคุณอยู่บน Oracle โดยบังเอิญหรือไม่
blah238

คำตอบ:


12

ก่อนอื่นได้แน่นอนคุณจะต้องแน่ใจว่าฟิลด์หลักและกุญแจต่างประเทศของคุณได้รับการจัดทำดัชนีในทั้งสองตาราง ซึ่งช่วยให้แผน DBMS และดำเนินการแบบสอบถามกับเขตข้อมูลเหล่านี้มีประสิทธิภาพมากขึ้น

ประการที่สองคุณกำลังโทรศัพท์SelectLayerByAttribute_managementในวงที่แน่นและซ้อนกัน (หนึ่งครั้งต่อต้นต่อการรักษา) สิ่งนี้ไม่มีประสิทธิภาพสูงด้วยเหตุผลหลายประการ:

  • คุณไม่จำเป็นต้องมีสองลูปหนึ่งอันซ้อนอยู่ภายในอีกอันสำหรับเรื่องนี้เท่าที่ฉันจะบอกได้ หนึ่งจะพอเพียง
  • ฟังก์ชันการประมวลผลทางภูมิศาสตร์เป็น "แบบหนา" และใช้เวลาในการโทรนานเมื่อเทียบกับฟังก์ชั่น Python ในตัว คุณควรหลีกเลี่ยงการโทรหาพวกเขาด้วยการวนซ้ำ
  • การขอบันทึก / ID ครั้งละหนึ่งรายการจะส่งผลให้มีการเดินทางไปยังฐานข้อมูลมากขึ้น

ให้ปรับรหัสของคุณใหม่เพื่อให้คุณเรียกSelectLayerByAttribute_managementเพียงครั้งเดียวโดยมีการสร้างคำสั่งที่เลือกไว้เพื่อเลือกระเบียนที่เกี่ยวข้องทั้งหมด

การยืมฟังก์ชั่นจากคำตอบอีกอันสำหรับตรรกะการสร้างวิสคอลด์ฉันคิดว่ามันจะมีหน้าตาแบบนี้:

def selectRelatedRecords(sourceLayer, targetLayer, sourceField, targetField):
    sourceIDs = set([row[0] for row in arcpy.da.SearchCursor(sourceLayer, sourceField)])
    whereClause = buildWhereClauseFromList(targetLayer, targetField, sourceIDs)
    arcpy.AddMessage("Selecting related records using WhereClause: {0}".format(whereClause))
    arcpy.SelectLayerByAttribute_management(targetLayer, "NEW_SELECTION", whereClause)

คุณสามารถเรียกมันว่า: selectRelatedRecords(treatment_tv, tree_fl, "Facility_ID", "FACILITYID")

หมายเหตุ:

  • สิ่งนี้ใช้arcpy.da.SearchCursorเพียง 10.1 เท่านั้น ตามที่ @PolyGeo พูดถึงเคอร์เซอร์เหล่านี้เร็วกว่ารุ่นก่อน ( arcpy.SearchCursor) สามารถแก้ไขได้อย่างง่ายดายเพื่อใช้ SearchCursor เก่าแม้ว่า:

    sourceIDs = set([row.getValue(sourceField) for row in arcpy.SearchCursor(sourceLayer, "", "", sourceField)])
  • หากฐานข้อมูล SDE ของคุณอยู่ใน Oracle ให้เตือนว่าINคำสั่งที่ใช้ในฟังก์ชั่นจากคำตอบที่เชื่อมโยงนั้น จำกัด ไว้ที่ 1,000 องค์ประกอบ คำตอบหนึ่งที่เป็นไปได้อธิบายไว้ในคำตอบนี้แต่คุณจะต้องแก้ไขฟังก์ชั่นเพื่อแยกมันออกเป็นINคำสั่งยาว 1,000 รายการหลายคำแทนที่จะเป็นหนึ่งคำสั่ง


5

วิธีการแก้ปัญหาข้างต้นใช้งานได้ดีสำหรับฉันและรวดเร็วมาก การใช้รหัสด้านบนและรหัสอ้างอิงจากโพสต์อื่นนี่คือวิธีที่ฉันสร้างขึ้น:

# Local Variables
OriginTable = "This must be a Table View or Feature Layer"
DestinationTable = "This must be a Table View or Feature Layer"
PrimaryKeyField = "Matching Origin Table Field"
ForiegnKeyField = "Matching Destination Table Field"

def buildWhereClauseFromList(OriginTable, PrimaryKeyField, valueList):
  """Takes a list of values and constructs a SQL WHERE
       clause to select those values within a given PrimaryKeyField
       and OriginTable."""

    # Add DBMS-specific field delimiters
    fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(OriginTable).path, PrimaryKeyField)

    # Determine field type
    fieldType = arcpy.ListFields(OriginTable, PrimaryKeyField)[0].type

    # Add single-quotes for string field values
    if str(fieldType) == 'String':
    valueList = ["'%s'" % value for value in valueList]

    # Format WHERE clause in the form of an IN statement
    whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(map(str, valueList)))
    return whereClause

def selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField):
    """Defines the record selection from the record selection of the OriginTable
      and applys it to the DestinationTable using a SQL WHERE clause built
      in the previous defintion"""

    # Set the SearchCursor to look through the selection of the OriginTable
    sourceIDs = set([row[0] for row in arcpy.da.SearchCursor(OriginTable, PrimaryKeyField)])

    # Establishes the where clause used to select records from DestinationTable
    whereClause = buildWhereClauseFromList(DestinationTable, ForiegnKeyField, sourceIDs)

    # Process: Select Layer By Attribute
    arcpy.SelectLayerByAttribute_management(DestinationTable, "NEW_SELECTION", whereClause)

# Process: Select related records between OriginTable and DestinationTable
selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.