[GIS] Setting list of fields to field mapping of spatial join using ArcPy

arcpyfield-mappingspatial-join

I try to code spatial join tool and delete some fields in the result. to delete the fields i list the fields of source layer and the result layer then use the list of differences in the two list and usedelete field management tool.it's working but not good solution.If i can set the Spatial Join field mapping to remain the source layer fields and only the "Distance_To_Next" field of the join layer, i get rid of some codes and iterates but don't know how to set the field mapping in the code.

Scripting spatial join in ArcPy to set field attribute in field mapping object? is the only result that i could find in the stack but not my answer.

import arcpy
arcpy.SpatialJoin_analysis("Point1", "point2","JoinResult","JOIN_ONE_TO_ONE","#","#","INTERSECT")
listfields1 = [fraft.name for fraft in arcpy.ListFields("Point1")]
listfields2 = [fraftv.name for fraftv in arcpy.ListFields("JoinResult")]
diff_fields = [i for i in listfields2 if not i in listfields1]
for field in diff_fields:
    if field != "Distance_To_Next":
        arcpy.DeleteField_management("JoinResult",field)

Best Answer

To manipulate the fields, their order, names, and other properties it is necessary to use the arcpy.FieldMappings() class. It is not very easy to get to know them and start using, so I've added extra comments to help you understand the workflow.

In this example, I am doing spatial join transferring just two fields from counties to cities.

import arcpy

cities = r'C:\Program Files (x86)\ArcGIS\Desktop10.4\TemplateData\TemplateData.gdb\USA\cities'
counties = r'C:\Program Files (x86)\ArcGIS\Desktop10.4\TemplateData\TemplateData.gdb\USA\counties'

#constructing an instance of <FieldMappings object>
fms = arcpy.FieldMappings()

#loading all field objects from counties into the <FieldMappings object>
fms.addTable(counties)

fields_sequence = ['CNTY_FIPS','CNTY_NAME']
#remove fieldmaps for those fields that are not needed in the output joined fc
fields_to_delete = [f.name for f in fms.fields if f.name not in fields_sequence]
for field in fields_to_delete:
    fms.removeFieldMap(fms.findFieldMapIndex(field))

#currently field mappings from counties have just two fields we have left
#[f.name for f in fms.fields] [u'NAME', u'CNTY_FIPS']

#now need to create a new fms and loat all fields from cities fc
#compiling output fms - all fields from cities
fms_out = arcpy.FieldMappings()
fms_out.addTable(cities)

# we need to add those two fields from counties
for field in fields_sequence:
    mapping_index = fms.findFieldMapIndex(field)
    field_map = fms.fieldMappings[mapping_index]
    fms_out.addFieldMap(field_map)

#[f.name for f in fms_out.fields] [all cities fields ] + [u'CNTY_FIPS',u'CNTY_NAME']

arcpy.SpatialJoin_analysis(target_features=cities, join_features=counties,
                          out_feature_class=r'C:\ArcGIS\scratch.gdb\resJoin',
                          join_operation='JOIN_ONE_TO_ONE',join_type='KEEP_ALL',
                          field_mapping=fms_out,match_option='WITHIN',
                          search_radius=None,distance_field_name=None)
Related Question