J'ai écrit un script Python qui fait une jointure spatiale et quelques calculs simples. Mon problème est de définir la règle de fusion pour un champ spécifique et de laisser les autres champs tels quels. Par exemple, j'ai un champ de population qui, lorsqu'il est joint par emplacement spatial, utilise la règle de fusion "First" qui saisit la première occurrence d'un compte de population. Je veux pouvoir définir la règle de fusion sur "Somme" pour additionner les valeurs de population entre tous les polygones trouvés dans l'étendue spatiale d'un autre polygone .
J'ai fait un bricolage intense avec des cartes de terrain et des objets de cartographie de terrain, mais je n'arrive pas à le faire fonctionner correctement. Plus précisément, j'ai essayé la méthode: popFieldMap.mergeRule = 'Sum' pour définir la mergeRule, mais elle revient toujours à "First".
Avez-vous des idées sur la façon dont je peux modifier par programme la règle de fusion pour un champ dans une jointure spatiale?
Merci!
Voici mon code (gardez à l'esprit qu'il est assez spécifique à mes données et contient des lignes pour tester certaines étapes du script):
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 - Ci-dessous le code avec la solution implémentée!
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()
population
champ?Réponses:
Je pense que vous devez réellement l'utiliser
FieldMappings.replaceFieldMap
pour qu'il persiste. Exemple tiré de la rubrique d'aide Mappage des champs d'entrée aux champs de sortie :Une autre pensée est que lorsque je teste des cartes de champs, j'aime utiliser un outil de script et un comportement d'outil de script personnalisé afin que je puisse inspecter visuellement la carte de champs au lieu d'essayer de décoder les longues chaînes folles qu'ils produisent.
Exemple
ToolValidator
classe que j'ai utilisé pour conclure que oui,replaceFieldMap
est nécessaire pour qu'il soit persistant dans la valeur du paramètre:la source