ArcPy kullanarak ilgili kayıtları verimli bir şekilde seçmek mi?


14

Aşağıda ArcMap "ilgili tablolar" düğmesini çoğaltmak için kullanıyorum kodu. ArcMap'te bu düğme, başka bir özellik sınıfı veya tablosundaki özellik seçimine bağlı olarak bir özellik sınıfındaki veya tablodaki özellikleri seçer.

ArcMap'te bu düğmeyi birkaç saniye içinde seçimimi ilgili tabloya "itmek" için kullanabilirim. Aynı görevi yapmak için bazı iç içe döngüler kullandığım için düğmeyi çoğaltan arcpy'de yerleşik bir şey bulamadım.

Aşağıdaki kod bir "tedaviler" tablosundan geçer. Her tedavi için, bir "ağaçlar" listesinden geçer. Tedavi alanlarıyla ağaçlar arasında bir eşleşme bulunduğunda, ağaç katmanında bir seçim gerçekleşir. Bir tedavi için eşleşme bulunduğunda, kod ek katmanlar için ağaç katmanını aramaya devam etmez. Tedavi tablosuna geri döner, bir sonraki tedaviyi seçer ve tekrar ağaç özellik sınıfını arar.

Kod kendisi iyi çalışıyor, ama agonizingly yavaş. Bu durumda "tedavi tablosu" 16.000 kayda sahiptir. "Ağaç" özellik sınıfının 60.000 kaydı vardır.

ESRI, seçimi bir tablodan diğerine aktardığında ne yaptığını yeniden oluşturmanın daha etkili bir yolu var mı? Tablolar için bir dizin oluşturmalı mıyım? NOT: Bu veriler bir SDE'de saklanır.

 # 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 mi kullanıyorsunuz? Öyleyse, arcpy.da.SearchCursor muhtemelen arcpy.SearchCursor'a göre çok daha hızlı (belki 10X) olacaktır. Ayrıca, bir Python sözlüğü kullanmayı da düşünebilirsiniz. Bunun gibi bir "anahtar dosya seçimi" nin burada
PolyGeo

SDE veritabanınız şans eseri Oracle üzerinde mi?
blah238

Yanıtlar:


12

Öncelikle, evet birincil ve yabancı anahtar alanlarınızın her iki tabloda da dizine eklendiğinden emin olmak isteyeceksiniz. Bu, DBMS'nin bu alanlara yönelik sorguları çok daha verimli bir şekilde planlamasına ve yürütmesine olanak tanır.

İkincisi, SelectLayerByAttribute_managementsıkı, iç içe bir döngüde (tedavi başına ağaç başına bir kez) çağırıyorsunuz . Bu, birkaç nedenden dolayı oldukça verimsizdir:

  • Biri diğerinin içine yerleştirilmiş iki döngüye ihtiyacınız yok, bunun için söyleyebildiğim kadarıyla. Kişi yeterli olacaktır.
  • Coğrafi işlem işlevleri "tıknaz" dır ve tipik yerleşik Python işlevlerine kıyasla aramak çok zaman alır. Bunları sıkı bir döngüde çağırmaktan kaçınmalısınız.
  • Bir kerede bir kayıt / kimlik istemek, veritabanına çok daha fazla gidiş dönüş sağlar.

Bunun yerine, SelectLayerByAttribute_managementtüm ilgili kayıtları seçmek için oluşturulmuş bir whereclause ile yalnızca bir kez çağırmanız için kodunuzu yeniden düzenleyin.

Whereeclause inşaat mantığı için başka bir cevaptan bir fonksiyon ödünç aldım, bunun böyle bir şey olacağını düşünürdüm:

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)

Buna şöyle diyebilirsiniz: selectRelatedRecords(treatment_tv, tree_fl, "Facility_ID", "FACILITYID")

Notlar:

  • Bu arcpy.da.SearchCursor, yalnızca 10.1 sürümünde kullanılabilen bir kullanır . @PolyGeo'nun belirttiği gibi, bu imleçler öncekilerden çok daha hızlıdır ( arcpy.SearchCursor). Yine de eski SearchCursor kullanmak için kolayca değiştirilebilir:

    sourceIDs = set([row.getValue(sourceField) for row in arcpy.SearchCursor(sourceLayer, "", "", sourceField)])
  • SDE coğrafi veritabanınız Oracle üzerindeyse IN, bağlantılı yanıttan işlevde kullanılan deyimin 1000 öğeyle sınırlı olduğu konusunda uyarılırsınız . Olası bir çözüm bu cevapta açıklanmıştır , ancak işlevi bir yerine birden çok 1000 uzunluklu INifadeye bölmek için işlevi değiştirmeniz gerekir .


5

Yukarıdaki çözüm benim için harika çalışıyor ve çok hızlıydı. Yukarıdaki kodu ve diğer yazı referans kodu kullanarak ben nasıl bu inşa:

# 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.