How to merge two feature classes and map multiple fields with different names but same type of content

2840
4
08-11-2017 05:03 PM
MTCGIS
by
New Contributor II

I'm working to develop a python script which merges two feature classes into one. I found the following arcpy example quite helpful, however it's only provides an example of how you might approach the problem of mapping input fields with different names and logically similar content for 1 input field from the 2 feature classes. My issue is that I have many fields from both input datasets which contain logically similar content. 

Example from ArcPy docs:

import arcpy

outfc = "C:/data/CityData.gdb/AllBlocks"

# Want to merge these two feature classes together. Have a field
#   that has the same content but the names are slightly different:
#   Blocks1 has TRACT2000 and Blocks2 TRACTCODE. Name the output
#   the same as Blocks1.
#
fc1 = "C:/data/CityData.gdb/Blocks1"
fc2 = "C:/data/CityData.gdb/Blocks2"

# Create a new fieldmappings and add the two input feature classes.
#
fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable(fc1)
fieldmappings.addTable(fc2)

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

# Remove the TRACTCODE fieldmap.
#
fieldmappings.removeFieldMap(fieldmappings.findFieldMapIndex("TRACTCODE"))

# Create a value table that will hold the inputs for Merge.
#
vTab = arcpy.ValueTable()
vTab.addRow(fc1)
vTab.addRow(fc2)

# Run the Merge tool.
#
arcpy.Merge_management(vTab, outfc, fieldmappings)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Does my question make sense?

0 Kudos
4 Replies
DanPatterson_Retired
MVP Emeritus

FieldMapping is the correct approach

But the field mapping control is used in... to quote

A number of geoprocessing tools, including Spatial Join, Append, Merge, Feature Class To Feature Class, and Table To Table, have a parameter for controlling how fields from the input datasets are processed and written, or mapped, to the output dataset—the Field Map parameter. In addition to the basic moving of attributes from input to output, field mapping can also be useful for some common tasks such as field concatenation and calculating statistics such as mean, sum, and standard deviation.

so check out the existing tools first.  If you need to do this multiple times, then you should do it manually once, and use the Results window to get the syntax correct.

MicahBabinski
Occasional Contributor III

For complicated field mapping operations (especially those with many input datasets) I like to store the field mapping information in a table and build the field mapping object from that. The key pieces of information are:

  • Output feature class
  • Input feature class
  • Input field name/output field name combination 

Build Arcpy Field Mapping Object from Table 

I found it a pain to use the field map control over a while - it's one of the clunkier aspects of ArcGIS geoprocessing tools.

Happy merging.

Micah

MTCGIS
by
New Contributor II

Hey Micah, 

Thanks so much for your reply! I took a look at your example but ended up going another way. For the most part, the two input feature classes that I wanted to merge had the same field names. It occurred to me that by leveraging the fieldmappings and fieldmap object, I could avoid associating each field from each input feature class with the destination field since identical fields would just be merged without my intervention (at least that seems like how it works...)

Here's what I did:

1) Created an empty FieldMappings object

2) Added tables from both input feature classes to the empty FieldMappings object

3) Created arrays of fields to be mapped from both input feature classes, careful to ensure that the index of the 

input field name was the same index as the input field name which it would be mapped to

4) Created a fieldmap dictionary object

5) Iterated over the objects keys/values,

  • found the field map in the field mappings object via field name
  • added my input field
  • updated field mappings object 
  • removed field map of input field was mapped

6)  Created a temp table to store feature class reference

7) Merged feature classes w/ updated field mapping 

Let me know what you think! Script below: 

#This script should be run within the ArcGIS Pro Python window

import arcpy 

outfc = r"TPA_Eligible_Transit_Stops_2017_test3"

# Merge the following two feature classes together - map fields with the same content to single field
# Each of the FC below were added to the project from MTC Organization ArcGIS Online

railfc = r"TPA_Non_Bus_Eligible_Stops_2017"
busfc = r"High_Frequency_Bus_Stops"

# Create a new fieldmappings object and add the two input feature classes

fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable(railfc)
fieldmappings.addTable(busfc)

#Get fieldmap for two fields in rail dataset which bus values will be merged into
#    - Create array of bus fields which are to be mapped (input fields)
#    - Create array of rail fields which bus fields will be mapped to (destination fields)
#    - Create dict using zip methold - ensure order of fields matches map - to order within array    

busfields = ["stop_id","lgcl_adjacent_hf_routes"]
railfields = ["agency_stop_id","Distance_Eligible"]
fieldmapdict = dict(zip(busfields,railfields))

#    - iterate over dictonary
#    - find field map for each rail field (destination field)
#    - add input field to fieldmap object (input field)
#    - replace field map (destination field map) within fieldmappings object with updated field
#    - remove bus field map from fieldmappings object (input field)

for busfield, railfield in fieldmapdict.items():
     fieldmap = fieldmappings.getFieldMap(fieldmappings.findFieldMapIndex(railfield))
     fieldmap.addInputField(busfc, busfield)
     fieldmappings.replaceFieldMap(fieldmappings.findFieldMapIndex(railfield), fieldmap)
     fieldmappings.removeFieldMap(fieldmappings.findFieldMapIndex(busfield)) 

#create temp value table and store fc paths as rows

vTab = arcpy.ValueTable()
vTab.addRow(railfc)
vTab.addRow(busfc)

#merge 

arcpy.Merge_management(vTab, outfc, fieldmappings)
RebeccaStrauch__GISP
MVP Emeritus

Since this is resolve, please make sure to mark the helpful comments and the one that resolved the issue...or mark it as assumed answered.  That will close the thread and allow others to find the answer. Thanks.

0 Kudos