ArcGIS 10'da “Alan Haritalama” - ArcPy


13

Uzamsal birleştirme ve bazı basit hesaplamalar yapan bir Python betiği yazdım . Benim sorunum, belirli bir alan için birleştirme kuralı ayarlamak ve geri kalan alanları olduğu gibi bırakmak. Örneğin, uzamsal konumla birleştirildiğinde , bir Nüfus sayımının ilk gerçekleşmesini sağlayan "İlk" birleştirme kuralını kullanan bir nüfus alanım var. Ben birleştirme kuralı ayarlamak mümkün istiyorum "Sum" için başka poligonun mekansal ölçüde bulunan çokgen tüm arasındaki nüfus değerleri toplarsınız .

Alan haritaları ve alan haritalama nesneleri ile bazı yoğun müdahaleler yaptım, ancak düzgün çalışmasını sağlayamıyorum. Özellikle mergeRule ayarlamak için yöntemi denedim: popFieldMap.mergeRule = 'Sum' , ama her zaman "İlk" olarak döner.

Herhangi bir fikir programsal olarak bir Spatial Join bir alan için birleştirme kuralını nasıl değiştirebilirim?

Teşekkürler!

İşte kodum (verilerime oldukça özel olduğunu ve komut dosyasının belirli aşamalarını test etmek için satırlar içerdiğini unutmayın):

import arcpy,sys,os

#Get the Files involved, set some variables.
SectorTable = sys.argv[1]
SectorShape = sys.argv[2]
MaxDev = sys.argv[3]
PopulationFC = sys.argv[4]
OutputFC = sys.argv[5]
DeviationField ="Angle_Deviation"
ID = "SectorID"
newID = "BP_ID"
mxd = arcpy.mapping.MapDocument('CURRENT')
df = arcpy.mapping.ListDataFrames(mxd)[0]

#Check to see if ID field types and name match
try:
    SectorShapeFields = arcpy.ListFields (SectorShape,ID)
    SectorTableFields = arcpy.ListFields (SectorTable,ID)
    arcpy.AddMessage("Finished Listing Fields")
    nameCheck = SectorShapeFields[0].name == SectorTableFields[0].name
    typeCheck = SectorShapeFields[0].type == SectorTableFields[0].type
except:
    arcpy.AddMessage("Failed to List Fields")

#If they do not match, add new fields to correct.
if not nameCheck:
    arcpy.AddMessage("Field Names do not match!  Adding new field to circumvent...")
if not typeCheck:
    arcpy.AddMessage("Field Types do not match!  Adding new field to circumvent...")
    if SectorShapeFields[0].type != SectorTableFields[0].type:
        try:
            arcpy.AddField_management(SectorShape, newID, SectorTableFields[0].type,10)
            arcpy.CalculateField_management(SectorShape, newID,"!"+ID+"!", "PYTHON")
            arcpy.RefreshTOC()
        except:
            arcpy.AddMessage("Error in Creating Field. Does it already exist?")


#Join the two together
arcpy.AddMessage("Performing Join")
arcpy.AddJoin_management( SectorShape, newID, SectorTable, ID)
arcpy.SelectLayerByAttribute_management (SectorShape,"NEW_SELECTION","Angle_Deviation>"+str(MaxDev))
df.zoomToSelectedFeatures()

#Field Mapping ...
myMap = arcpy.FieldMappings()
myMap.addTable(PopulationFC)
myMap.addTable(SectorShape)

#Verify the field merge rule for the pop10 field.
fIndex = myMap.findFieldMapIndex("POP10")
arcpy.AddMessage(str(fIndex))
popFieldMap = myMap.getFieldMap(fIndex)
arcpy.AddMessage(str(popFieldMap.mergeRule))
popFieldMap.mergeRule = 'Sum'
arcpy.AddMessage(str(popFieldMap.mergeRule))
popFieldMap2 = popFieldMap

##Test
fIndex = myMap.findFieldMapIndex("POP10")
arcpy.AddMessage(str(fIndex))
popFieldMap = myMap.getFieldMap(fIndex)
arcpy.AddMessage(str(popFieldMap.mergeRule))

#Perform Spatial Join
arcpy.AddMessage("Performing Spatial Join")
arcpy.SpatialJoin_analysis(SectorShape, PopulationFC, OutputFC,"JOIN_ONE_TO_ONE","",myMap,"INTERSECT")

#Add Result and Symbolize
arcpy.mapping.AddLayer(df,arcpy.mapping.Layer(OutputFC))
translayer = arcpy.mapping.ListLayers(mxd,"",df)[0]
translayer.transparency = 50

arcpy.RefreshActiveView()

EDIT - Aşağıda uygulanan çözüm ile kod!

import arcpy,sys,os

#Get the Files involved, set some variables.
SectorTable = sys.argv[1]
SectorShape = sys.argv[2]
MaxDev = sys.argv[3]
PopulationFC = sys.argv[4]
OutputFC = sys.argv[5]
DeviationField ="Angle_Deviation"
ID = "SectorID"
newID = "BP_ID"
mxd = arcpy.mapping.MapDocument('CURRENT')
df = arcpy.mapping.ListDataFrames(mxd)[0]

#Check to see if ID field types and name match
try:
    SectorShapeFields = arcpy.ListFields (SectorShape,ID)
    SectorTableFields = arcpy.ListFields (SectorTable,ID)
    arcpy.AddMessage("Finished Listing Fields")
    nameCheck = SectorShapeFields[0].name == SectorTableFields[0].name
    typeCheck = SectorShapeFields[0].type == SectorTableFields[0].type
except:
    arcpy.AddMessage("Failed to List Fields")

#If they do not match, add new fields to correct.
if not nameCheck:
    arcpy.AddMessage("Field Names do not match!  Adding new field to circumvent...")
if not typeCheck:
    arcpy.AddMessage("Field Types do not match!  Adding new field to circumvent...")
    if SectorShapeFields[0].type != SectorTableFields[0].type:
        try:
            arcpy.AddField_management(SectorShape, newID, SectorTableFields[0].type,10)
            arcpy.CalculateField_management(SectorShape, newID,"!"+ID+"!", "PYTHON")
            arcpy.RefreshTOC()
        except:
            arcpy.AddMessage("Error in Creating Field. Does it already exist?")


#Join the two together
arcpy.AddMessage("Performing Join")
arcpy.AddJoin_management( SectorShape, newID, SectorTable, ID)
arcpy.SelectLayerByAttribute_management (SectorShape,"NEW_SELECTION","Angle_Deviation>"+str(MaxDev))
df.zoomToSelectedFeatures()

#Field Mapping ...
myMap = arcpy.FieldMappings()
myMap.addTable(PopulationFC)
myMap.addTable(SectorShape)

#Verify the field merge rule for the pop10 field.
fIndex = myMap.findFieldMapIndex("POP10")
arcpy.AddMessage(str(fIndex))
popFieldMap = myMap.getFieldMap(fIndex)
arcpy.AddMessage(str(popFieldMap.mergeRule))
popFieldMap.mergeRule = 'Sum'
arcpy.AddMessage(str(popFieldMap.mergeRule))

myMap.replaceFieldMap(fIndex,popFieldMap)

##Test
fIndex = myMap.findFieldMapIndex("POP10")
arcpy.AddMessage(str(fIndex))
popFieldMap = myMap.getFieldMap(fIndex)
arcpy.AddMessage(str(popFieldMap.mergeRule))

#Perform Spatial Join
arcpy.AddMessage("Performing Spatial Join")
arcpy.SpatialJoin_analysis(SectorShape, PopulationFC, OutputFC,"JOIN_ONE_TO_ONE","",myMap,"INTERSECT")

#Add Result and Symbolize
arcpy.mapping.AddLayer(df,arcpy.mapping.Layer(OutputFC))
translayer = arcpy.mapping.ListLayers(mxd,"",df)[0]
translayer.transparency = 50

arcpy.RefreshActiveView()

1
Senaryonuzu gönderebilir misiniz?
blah238

Tabii, yayınlayayım. Kodumun test adımları olarak eklediğim bazı bölümleri olduğunu unutmayın.
Pixel

populationAlanın veri türünü kontrol ettiniz mi?
Alex Markov

ilk eğim, muhtemelen pop alanının bir metin türü olmasıdır.
Brad Nesom

Alan Türü "Uzun", bu nedenle matematiksel toplamı yapmaya uygun olmalı, değil mi?
Pixel

Yanıtlar:


14

Bence bunu FieldMappings.replaceFieldMapsürdürebilmek için kullanmalısın. Yardım konusundan örnek Giriş alanlarını çıktı alanlarıyla eşleme :

# First get the TRACT2000 fieldmap. Then add the TRACTCODE field
#   from Blocks2 as an input field. Then replace the fieldmap within
#   the fieldmappings object.
#
fieldmap = fieldmappings.getFieldMap(fieldmappings.findFieldMapIndex("TRACT2000"))
fieldmap.addInputField(fc2, "TRACTCODE")
fieldmappings.replaceFieldMap(fieldmappings.findFieldMapIndex("TRACT2000"), fieldmap)

Başka bir düşünce, alan haritaları test ederken, bir betik aracı ve özel komut dosyası aracı davranışını kullanmayı seviyorum, böylece ürettikleri çılgın uzun dizeleri deşifre etmek yerine alan haritasını görsel olarak inceleyebilirim.

Örnek ToolValidatorsınıf I, evet, replaceFieldMapparametre değerinde kalıcı olması için gerekli olduğu sonucuna vardı.

class ToolValidator:
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    import arcpy
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parmater
    has been changed."""
    if (not self.params[0].hasBeenValidated
    or not self.params[1].hasBeenValidated):
        targetFeatures = self.params[0].value
        joinFeatures = self.params[1].value
        fieldMappings = arcpy.FieldMappings()
        if targetFeatures:
            fieldMappings.addTable(targetFeatures)
            if joinFeatures:
                fieldMappings.addTable(joinFeatures)
                idx = fieldMappings.findFieldMapIndex("PRIORITY")
                fieldMap = fieldMappings.getFieldMap(idx)
                fieldMap.mergeRule = 'Sum'
                fieldMappings.replaceFieldMap(idx, fieldMap) # if this line is commented out, the merge rule reverts to 'First'
        self.params[3].value = fieldMappings.exportToString()
    return

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return

Güzel düşünce, içine bakayım ve senaryomda nereye uygulayacağımı göreyim. Bulgularımla geri göndereceğim
Pixel

2
Bu sorunu çözen harika bir cevaptı. Ayrıca, sorunun nedeni hakkında büyük ayrıntı sağladığınız için teşekkür ederiz! :)
Piksel
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.