“ การแมปฟิลด์” ใน ArcGIS 10 - ArcPy


13

ฉันได้เขียนสคริปต์Pythonที่เข้าร่วมเชิงพื้นที่และการคำนวณง่ายๆ ปัญหาของฉันคือการตั้งค่ากฎการผสานสำหรับเขตข้อมูลหนึ่งโดยเฉพาะและปล่อยให้ส่วนที่เหลือของฟิลด์เหมือนเดิม ตัวอย่างเช่นฉันมีเขตข้อมูลประชากรที่เมื่อรวมตำแหน่งเชิงพื้นที่โดยใช้กฎการรวม"ครั้งแรก"ซึ่งจะจับการนับจำนวนครั้งแรกที่เกิดขึ้น ฉันต้องการที่จะสามารถที่จะตั้งกฎการผสานการ"ซำ"ที่จะเพิ่มค่าประชากรระหว่างทั้งหมดของรูปหลายเหลี่ยมที่พบในขอบเขตพื้นที่ของรูปหลายเหลี่ยมอีก

ฉันได้ทำการซ่อมแซมที่รุนแรงด้วยฟิลด์แผนที่และวัตถุการแมปฟิลด์ แต่ดูเหมือนว่าจะทำงานไม่ถูกต้อง ฉันลองใช้วิธีเฉพาะ: popFieldMap.mergeRule = 'Sum'เพื่อตั้งค่า mergeRule แต่จะเปลี่ยนเป็น "First" เสมอ

แนวคิดใดที่ฉันสามารถเปลี่ยนกฎการรวมโดยทางโปรแกรมสำหรับเขตข้อมูลหนึ่งในการเข้าร่วมเชิงพื้นที่ได้

ขอบคุณ!

นี่คือรหัสของฉัน (โปรดทราบว่ามันค่อนข้างเฉพาะเจาะจงกับข้อมูลของฉันและมีบรรทัดเพื่อทดสอบขั้นตอนบางอย่างของสคริปต์):

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

แก้ไข - ด้านล่างเป็นรหัสพร้อมโซลูชันที่ใช้งาน!

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
คุณสามารถโพสต์สคริปต์ของคุณ?
blah238

แน่นอนให้ฉันโพสต์มันขึ้นมา โปรดทราบว่ามีบางส่วนของรหัสของฉันที่ฉันแทรกเป็นขั้นตอนการทดสอบ
Pixel

คุณได้ตรวจสอบประเภทข้อมูลของpopulationเขตข้อมูล?
อเล็กซ์มาร์คอฟ

ความโน้มเอียงแรกของฉันคือว่าช่องป๊อปอาจเป็นประเภทข้อความ
แบรด Nesom

ประเภทฟิลด์คือ "ยาว" ดังนั้นจึงควรมีสิทธิ์ดำเนินการสรุปทางคณิตศาสตร์ใช่ไหม
Pixel

คำตอบ:


14

ฉันคิดว่าคุณต้องใช้FieldMappings.replaceFieldMapเพื่อทำให้มันคงอยู่ ตัวอย่างจากหัวข้อวิธีใช้การแม็พฟิลด์อินพุตกับฟิลด์เอาต์พุต :

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

อีกความคิดหนึ่งคือเมื่อทำการทดสอบการแมปภาคสนามฉันชอบที่จะใช้เครื่องมือสคริปต์และลักษณะการทำงานของเครื่องมือสคริปต์แบบกำหนดเองดังนั้นฉันจึงสามารถตรวจสอบแผนที่ภาคสนามด้วยสายตาแทนการพยายามถอดรหัสสตริงยาว ๆ ที่พวกมันสร้างขึ้น

ตัวอย่างToolValidatorคลาสที่ฉันใช้เพื่อสรุปว่าใช่replaceFieldMapจำเป็นสำหรับการคงอยู่ในค่าพารามิเตอร์:

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

ความคิดดีให้ฉันดูมันและดูว่าฉันจะใช้มันในสคริปต์ของฉัน ฉันจะโพสต์กลับด้วยการค้นพบของฉัน
Pixel

2
นี่เป็นคำตอบที่ยอดเยี่ยมในการแก้ไขปัญหา นอกจากนี้ขอขอบคุณสำหรับการให้รายละเอียดที่ดีเกี่ยวกับสาเหตุของปัญหา! :)
Pixel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.