Select to view content in your preferred language

Using FieldMappings in Arcpy for one feature class

519
5
12-13-2023 04:32 PM
KateKnowles
New Contributor

I am trying to use FieldMappings in Arcpy to re-order columns in a feature class. I perform a variety of functions on this feature class in my script including adding fields, renaming fields, doing a spatial join, and adding an attribute rule. After all of this, I would like to re-order the fields, but I have not been able to figure out a way to do that. I was able to use the field mappings argument within the spatial join tool (shown below) but I have not been able to do it using FieldMappings(). 

This is what works:

 

arcpy.analysis.SpatialJoin(
    target_features = fc_bl_temp,
    join_features = fc_tr_70_out_j,
    out_feature_class = fc_bl_out,
    join_operation = "JOIN_ONE_TO_ONE",
    join_type = "KEEP_ALL",
    field_mapping = 'STATE70 "STATE70" true true false 2 Text 0 0, First,#,fc_bl_temp,STATE70,0,2;COUNTY70 "COUNTY70" true true false 3 Test 0 0, First,#,fc_bl_tem,COUNTY70,0,3;TRACT80 "TRACT80" true true false 10 Text 0 0, First,#,fc_bl_temp,TRACT80,0,10;BLK70 "BLK70" true true false 3 Text 0 0,First,#,fc_bl_temp,BLK70,0,3;Shape_Length "Shape_Length" false true true 8 Double 0 0,First,#,fc_bl_temp,Shape_Length,-1,-1;Shape_Area "Shape_Area" false true true 8 Double 0 0,First,#,fc_bl_temp,Shape_Area,-1,-1',
    match_option="HAVE_THEIR_CENTER_IN",
    search_radius = None,
    distance_field_name = ""
)​

 

Most of the documentation I'm seeing is for combining two feature classes to create a new one or merge of some sort, but I'm struggling to translate those examples to my use case with a single feature class that I am not trying to change in any other way. Does anyone have any ideas for how to approach re-ordering ~10 fields in one feature class?
0 Kudos
5 Replies
DanPatterson
MVP Esteemed Contributor

could

Export Features (Conversion)—ArcGIS Pro | Documentation

be part of the workflow given it allows for field alteration


... sort of retired...
0 Kudos
KateKnowles
New Contributor

Thanks Dan I will give that a shot!

0 Kudos
BlakeTerhune
MVP Regular Contributor

I always have trouble wrapping my brain around field mappings. I recommend using the FieldMappings object whenever possible. It's much easier than trying to parse/manage that giant string. I made this a while back to build a reordered FieldMappings object. Maybe you can adapt it to fit your needs.

 

import arcpy
import os

def reorder_fields(table, out_table, field_order, add_missing=True):
    """
    Based on code by Josh Werts, Apr 17th, 2014
    http://joshwerts.com/blog/2014/04/17/arcpy-reorder-fields/
    Reorders fields in input featureclass/table
    :table:         input table (fc, table, layer, etc)
    :out_table:     output table (fc, table, layer, etc)
    :field_order:   order of fields (objectid, shape not necessary)
    :add_missing:   add missing fields to end if True (leave out if False)
    -> path to output table
    """
    existing_field_names = [field.name for field in arcpy.ListFields(table)]

    existing_mapping = arcpy.FieldMappings()
    existing_mapping.addTable(table)

    new_mapping = arcpy.FieldMappings()

    def add_mapping(field_name):
        mapping_index = existing_mapping.findFieldMapIndex(field_name)

        # required fields (OBJECTID, etc) will not be in existing mappings
        # they are added automatically
        if mapping_index != -1:
            field_map = existing_mapping.getFieldMap(mapping_index)
            new_mapping.addFieldMap(field_map)

    # add user fields from field_order
    for field_name in field_order:
        if field_name not in existing_field_names:
            raise Exception("{0} field doesn't exist in {1}".format(field_name, os.path.split(table)[1]))

        add_mapping(field_name)

    # add missing fields at end
    if add_missing:
        missing_fields = [f for f in existing_field_names if f not in field_order]
        for field_name in missing_fields:
            add_mapping(field_name)

    return new_mapping


def main():
    inGDB = r"C:\my folder\mydata.gdb"
    inTable = os.path.join(inGDB, "TEMP_Line")
    outGDB = r"C:\my folder\maybeanother.gdb"
    outTable = os.path.join(outGDB, "TEMP_Line_reordered")

    new_field_order = [
        'NewFieldName',
        'SHAPE_Length',
        'Note1',
        'Note2',
        'asdf',
    ]
    new_fieldmappings = reorder_fields(inTable, outTable, new_field_order)
    # Do something with the new fieldmappings...


if __name__ == '__main__':
    main()

 

0 Kudos
KateKnowles
New Contributor

Hi @BlakeTerhune

Thanks for the sample code! Since I'm not trying to make any changes to the feature class, one of my problems is I'm not sure what to do with the new fieldmappings. Could the output from your code go into the Export Features tool @DanPatterson suggested above? 

0 Kudos
BlakeTerhune
MVP Regular Contributor

Yes. The FieldMappings can be used in any function that has a field map parameter of type "Field Mappings."

0 Kudos