Append Tool and Field Mapping ... Help? Examples?

23714
21
Jump to solution
11-03-2016 08:19 AM
Brownschuh
Occasional Contributor II

Having a bit of trouble with the field mapping component of the append tool; I cannot seem to get it to work properly as I am left with a feature class that is populated with all the features, but the attribute table remains blank. 

Background info: I have two feature classes in an enterprise geodatabase with address point data.  One is the authoritative source edited by our address coordinator and the other is used as to host a map service.  The data is essentially the same, but the schemas are slightly different; half of the fields are the exactly the same, but others have different names.  My workflow has been to update the 'map service' feature class on a daily basis by deleting all the records and loading the data manually, selecting the NO_TEST option, and manually mapping the fields where the names are different ... but this is where I run into trouble with my script.

I've ran the append process manually using the geoprocessing tool and copied the python snippet of the field mapping component and am left with an output attribute table that has all null values.  Ideally I'd like to move away from this style of coding as I am aware it can be rather clunky/lengthy ... and it just does not work (even though it throws no errors).

I'd like to do 'real' field mapping, but so far the examples I've found have a bit more complicated or focus mainly on the Merge tool.  I'd like to see a nice, simple Append tool example if possible.

Also, how does field mapping work if some fields are the same and others are different? I haven't run across a good example that deals with this problem.

Here are some of the sources I've looked at so far:

Field mapping and Python scripting | ArcGIS Blog

Mapping input fields to output fields—ArcPy Get Started | ArcGIS for Desktop 

21 Replies
gkanazawa_Mpls
New Contributor II

I'm picking this thread back up as I'm also trying to do the same thing (Append data from one feature class to another with a different schema via Field Mapping. Following Luke Webb's method above, I'm also running into problems at that same line of code within the 'for' loop, and I can't figure out what's wrong: 

field_to_map.addInputField(append_layer, field_map[1])

The tool gets tripped up at that line and throws 'RuntimeError: FieldMap: Error in adding input field to field map'. In my text editor (VS Code), it doesn't look like the script is accessing the methods associated with the FieldMap object, which, correct me if I'm wrong, but that is what "field_to_map" is here, right?

Were you ever able to resolve this issue?

Thanks!

0 Kudos
LukeWebb
Occasional Contributor III

My understanding of field mappings is you create an empty fieldmap.

fieldmappings = arcpy.FieldMappings()

Then you popupulate it using tables like we did, or alternatively you could do it totally manually as the example on the help page shows. There they create an output field mapping that has 2 fields. It looks pretty complex but heres a simple, 1 field output map!

input_file1 = 'data.gdb/Trees'
input_file2 = 'Plants.shp'

######You could loop this bit
field_map = arcpy.FieldMap()
field_name_input_file1 = "Tree_Type"
field_name_input_file2 = "Tree_Species"
field_map.addInputField(input_file1, field_name_input_file1)
field_map.addInputField(input_file2, field_name_input_file2)
field_map.name = 'Tree_Classification'
fieldmappings.addFieldMap(field_map)

With this in mind, our output fieldmap we have created, actually contains all of the 'target' and all of the 'append' layers fields, but as you are running append you dont see all the unmatched 'append' fields in the output. If you ran the same field map through a merge, you would end up with all the append layers fields as well.

Brownschuh
Occasional Contributor II

After a bit of trial and error, here's the approach I took:

   field_to_map_index1 = fieldmappings.findFieldMapIndex("Permanent_Identifier")
   field_to_map_index2 = fieldmappings.findFieldMapIndex("DateAdded")

   field_to_map1 = fieldmappings.getFieldMap(field_to_map_index1)
   field_to_map2 = fieldmappings.getFieldMap(field_to_map_index2)

   field_to_map1.addInputField(Address_Points, "TaxPIN")
   field_to_map2.addInputField(Address_Points, "created_date")

Looks like it's similar to what you posted above.

"With this in mind, our output fieldmap we have created, actually contains all of the 'target' and all of the 'append' layers fields, but as you are running append you dont see all the unmatched 'append' fields in the output. If you ran the same field map through a merge, you would end up with all the append layers fields as well."

/\ This is good to know, appreciate the clarification.  And thank you for the help!!

ChrisHolmes
Occasional Contributor III

Bringing this thread back to life.

Is it possible to accomplish the following using the field mappings. I would like values for two of the fields in the target dataset to come from parameters entered by the user when the script is run? If so, does anyone have a snippet of code that would show how to work the parameter values into the fields mappings.

Thanks,

Chris

0 Kudos
NeilAyres
MVP Alum

Field maps are about the definitions of the columns, names, alias, type etc and automatically point the content of one column to another.

If you want to alter content you will have to use a field calculator or a da.UpdateCursor

ChrisHolmes
Occasional Contributor III

Thanks for clearing that up Neil. I was working on a script with an update cursor to use after the append tool but what I’m noticing is that after the append tool finishes the target shape is not selected so I’ll have to figure out either a way to select it or a way to select it using a search cursor prior to doing the update. Thanks!

0 Kudos
NeilAyres
MVP Alum

Or just run through the UpdateCursor and update only where your search column equals the value you are looking for.

0 Kudos
ShawnRoberts1
Occasional Contributor

I found the syntax in the examples very confusing as well! The above example provided by Luke got my code off the ground, so I figured I'd post my little solution. Maybe it will be of help to someone as well.

Essentially I just call this function before I run the tool requiring the field map (append,merge ect).The dictionary is contains the "in"( and "out values", then it just iterates through each item in the dictionary and assigns the field map values.

Only note I'm using python 3.X so .iteritems() isn't available. 

def fieldMapping(fc_in,fc_out):
    try:
        # value in the 'in' feature class, value in the feature class to be appended to
        dico = {'Assessed_Value': 'ARN', 'Total_Value': 'TotalValue'}

        fieldmappings = arcpy.FieldMappings()
        fieldmappings.addTable(fc_in)
        fieldmappings.addTable(fc_out)

        for input,output in dico.items():
            field_to_map_index = fieldmappings.findFieldMapIndex(output)
            field_to_map = fieldmappings.getFieldMap(field_to_map_index)
            field_to_map.addInputField(fc_in,input)
            fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

        return fieldmappings

    except:
        logging.exception('Generic error raised during fieldmap creation')
        raise


TonyAlmeida
Occasional Contributor II

Here is what i use, i found this in a thread in this forum but i can't find the link. I had a hard time understanding field mapping until i cam across this code. Since i can't find the thread i can't explain all the syntax. Maybe someone can shine in and explain the syntax please?

UG1A = "C:/Temp/Scratchworkspace.gdb/lyr1"
IRRG = "D:/GIS Folder/lyr2"

def Layers2(FZon1,UG1A,IRRG):
    FieldMapString = "" \
                
                + """PIN "PIN" true true false 13 Text 0 0 ,First,#,""" + UG1A + """,Pin,-1,-1;"""\
                + """ACRES "ACRES" true true false 4 Double 0 0  ,First,#,""" + UG1A + """,ACRES,-1,-1;"""\
                + """Instrument "Instrument" true true false 10 Text 0 0 ,First,#,""" + UG1A + """,Instrument,-1,-1;"""\
                + """SiteAddres "SiteAddres" true true false 106 Text 0 0 ,First,#,""" + UG1A + """,SiteAddres,-1,-1;"""\
                + """SiteCity "SiteCity" true true false 32 Text 0 0 ,First,#,""" + UG1A+ """,SiteCity,-1,-1;"""\
                + """SiteZip "SiteZip" true true false 10 Text 0 0 ,First,#,""" + UG1A + """,SiteZip,-1,-1;"""\
                + """UG_NAME "UG_NAME" true false false 20 Text 0 0 ,First,#,"""+ UG1A + """,UG_NAME,-1,-1;"""\
                + """IRRIG_DIST "IRRIG_DIST" true false false 60 Text 0 0 ,First,#,"""+ IRRG + """,NAME,-1,-1;"""\


    fieldmappings = arcpy.FieldMappings()
    fieldmappings.loadFromString(FieldMapString)
    return fieldmappings

def main(args=None):
        if args is None:
                args = sys.argv
                
arcpy.SpatialJoin_analysis(UG1A, IRRG, "C:\Temp\Scratchworkspace.gdb\lyr3",
                           "JOIN_ONE_TO_ONE", "KEEP_ALL", Layers2(FZon1,UG1A,IRRG), "INTERSECT")
0 Kudos
AllenDailey1
Occasional Contributor III

I have a similar situation; I used Model Builder to export a python file.  I am wondering what do the "true true false" etc. in the field map syntax mean or represent?

Did you ever find out?

Thanks!

Allen

0 Kudos