आर्कपी का उपयोग करके संबंधित रिकॉर्डों का कुशलतापूर्वक चयन करना?


14

नीचे आर्कब में "संबंधित तालिकाओं" बटन को दोहराने के लिए मैं कोड का उपयोग कर रहा हूं। ArcMap में वह बटन किसी एक सुविधा वर्ग या तालिका में किसी अन्य संबंधित सुविधा वर्ग या तालिका में सुविधाओं के चयन के आधार पर सुविधाओं का चयन करता है।

ArcMap में मैं सेकंड के एक मामले में संबंधित चयन के लिए मेरे चयन को "पुश" करने के लिए उस बटन का उपयोग कर सकता हूं। मैं आर्कपी में निर्मित कुछ भी खोजने में असमर्थ था जो बटन को दोहराता है इसलिए मैंने उसी कार्य को करने के लिए कुछ नेस्टेड छोरों का उपयोग किया।

नीचे दिए गए कोड "उपचार" की एक तालिका के माध्यम से छोरों। प्रत्येक उपचार के लिए, यह "पेड़ों" की एक सूची से गुजरता है। जब उपचार और पेड़ों के आईडी क्षेत्रों के बीच एक मैच पाया जाता है, तो पेड़ की परत में एक चयन होता है। एक बार जब एक उपचार के लिए एक मैच पाया जाता है, तो कोड अतिरिक्त मैचों के लिए पेड़ की परत को खोजना जारी नहीं रखता है। यह उपचार तालिका में वापस जाता है, अगले उपचार का चयन करता है और फिर से ट्री फीचर क्लास के माध्यम से खोज करता है।

कोड स्वयं ठीक काम करता है, लेकिन यह आश्चर्यजनक रूप से धीमा है। इस मामले में "उपचार तालिका" में 16,000 रिकॉर्ड हैं। "ट्री" फीचर क्लास में 60,000 रिकॉर्ड हैं।

क्या ईएसआरआई क्या कर रहा है इसे चुनने के लिए एक और अधिक कुशल तरीका है जब यह चयन को एक मेज से दूसरे तक पहुंचाता है? क्या मुझे तालिकाओं के लिए एक सूचकांक बनाना चाहिए? नोट: यह डेटा एक एसडीई में संग्रहीत है।

 # 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
क्या आप आर्कगिस 10.1 का उपयोग कर रहे हैं? यदि ऐसा है, तो arcpy.da.SearchCursor के लिए arcpy.SearchCursor की तुलना में बहुत तेज़ (शायद 10X) होने की संभावना है। इसके अलावा, आप पायथन डिक्शनरी के उपयोग पर विचार कर सकते हैं। मुझे लगता है कि इस तरह एक "keyfile चयन" बहुत लाभ हो सकता है से दृष्टिकोण का इस्तेमाल किया यहाँ
PolyGeo

क्या आपका SDE डेटाबेस Oracle के संयोग से है?
blah238

जवाबों:


12

सबसे पहले, हां आप निश्चित रूप से यह सुनिश्चित करना चाहेंगे कि आपके प्राथमिक और विदेशी कुंजी फ़ील्ड दोनों तालिकाओं पर अनुक्रमित हैं। यह DBMS योजना और इन क्षेत्रों के खिलाफ प्रश्नों को अधिक कुशलता से निष्पादित करता है।

दूसरे, आप SelectLayerByAttribute_managementएक तंग, नेस्टेड लूप (एक बार प्रति पेड़ प्रति उपचार) में बुला रहे हैं । यह कई कारणों से अत्यधिक अक्षम है:

  • आपको दो छोरों की आवश्यकता नहीं है, एक दूसरे के भीतर घोंसला है, इसके लिए, जहां तक ​​मैं बता सकता हूं। एक ही पर्याप्त होगा।
  • जियोप्रोसेसिंग फ़ंक्शन "चंकी" हैं और विशिष्ट अंतर्निहित पायथन कार्यों की तुलना में कॉल करने के लिए बहुत समय लेते हैं। आपको उन्हें तंग पाश में कॉल करने से बचना चाहिए।
  • एक बार में एक रिकॉर्ड / आईडी मांगने से डेटाबेस में बहुत अधिक गोल यात्राएं होती हैं।

इसके बजाय, अपने कोड को 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)])
  • यदि आपका एसडीई जियोडैटेबेस ओरेकल पर है, तो चेतावनी दी जाती है कि INलिंक किए गए उत्तर से फ़ंक्शन में उपयोग किया गया कथन 1000 तत्वों तक सीमित है। इस उत्तर में एक संभावित समाधान का वर्णन किया गया है , लेकिन आपको INएक के बजाय कई 1000-लंबाई के बयानों में विभाजित करने के लिए फ़ंक्शन को संशोधित करना होगा ।


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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.