“Field Mapping” di ArcGIS 10 - ArcPy


13

Saya telah menulis skrip Python yang menggabungkan spasial dan beberapa perhitungan sederhana. Masalah saya adalah dengan menetapkan aturan gabungan untuk satu bidang tertentu, dan membiarkan bidang lainnya seperti apa adanya. Sebagai contoh, saya memiliki bidang populasi yang ketika bergabung dengan lokasi spasial menggunakan aturan gabungan "Pertama" yang mengambil yang pertama kali terjadi dari jumlah populasi. Saya ingin dapat menetapkan aturan gabungan ke "Jumlah" untuk menjumlahkan nilai populasi antara semua poligon yang ditemukan dalam tingkat spasial poligon lain .

Saya telah melakukan beberapa mengutak-atik peta bidang dan objek pemetaan lapangan, tetapi tampaknya tidak bisa berfungsi dengan benar. Secara khusus saya telah mencoba metode ini: popFieldMap.mergeRule = 'Jumlah' untuk mengatur mergeRule, tetapi selalu kembali ke "Pertama".

Adakah gagasan bagaimana saya secara terprogram dapat mengubah aturan gabungan untuk satu bidang dalam Gabung Spasial?

Terima kasih!

Ini kode saya (perlu diingat bahwa kode ini cukup spesifik untuk data saya dan berisi baris untuk menguji tahapan tertentu dari skrip):

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 - Di bawah ini adalah kode dengan solusi diimplementasikan!

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
Bisakah Anda memposting skrip Anda?
blah238

Tentu, izinkan saya mempostingnya. Perlu diingat bahwa ada bagian dari kode saya yang saya masukkan sebagai langkah pengujian.
Pixel

Sudahkah Anda memeriksa tipe data populationbidang?
Alex Markov

Kecenderungan pertama saya adalah bahwa mungkin bidang pop adalah tipe teks.
Brad Nesom

Jenis Bidang adalah "Panjang", jadi harus memenuhi syarat untuk melakukan penjumlahan matematis, benar?
Pixel

Jawaban:


14

Saya pikir Anda harus benar-benar menggunakan FieldMappings.replaceFieldMapuntuk membuatnya bertahan. Contoh dari topik bantuan Memetakan bidang input ke bidang output :

# 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)

Pemikiran lain adalah ketika menguji peta bidang, saya suka menggunakan alat skrip dan perilaku alat skrip kustom sehingga saya dapat secara visual memeriksa peta bidang alih-alih mencoba memecahkan kode string panjang gila yang mereka hasilkan.

ToolValidatorKelas contoh yang saya gunakan untuk menyimpulkan bahwa ya, replaceFieldMapdiperlukan untuk itu akan bertahan dalam nilai parameter:

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

Pikiran yang bagus, biarkan saya melihatnya dan melihat di mana saya akan menerapkannya dalam skrip saya. Saya akan memposting kembali dengan temuan saya
Pixel

2
Ini adalah jawaban yang bagus untuk menyelesaikan masalah. Juga, terima kasih telah memberikan perincian besar tentang penyebab masalahnya! :)
Pixel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.