1

I have two feature classes that I need to merge to a single layer. There are ~10 common fields that I need to preserve and each of the two layers has some fields that are not shared.

I know that I could first DeleteField_management() each layer to have layers with identical fields and then do a simple merge but it seems like I should be able to use Merge_management() and a field mapping. I don't see how to include/exclude fields though, only how to transform them.

Inputs: file_1 with fields a,b,c,d. file_2 with fields c,d,e,f.

Desired output: file_3 with fields c,d.

  • Is your goal to achieve the best performance or are you just trying to figure out the "right" way to do things? – mikewatt Sep 1 at 17:53
  • It just seemed like there should be a straightforward way to do this that was cleaner than looping through everything to collect a list of fields to delete. Plus to use DeleteField I really need to copy the two layers and then delete from to avoid changing the input data. – Hugh_Kelley Sep 1 at 18:02
2

This is potentially less performant than Emil's answer, but much more concise: just merge everything indiscriminately, create 2 sets with the original field names, then delete the symmetric difference of those field names (belonging to either fc_a or fc_b, but not both).

merged = arcpy.Merge_management([fc_a, fc_b], 'merged')
fields_a = {field.name for field in arcpy.ListFields(fc_a)}
fields_b = {field.name for field in arcpy.ListFields(fc_b)}
arcpy.DeleteField_management(merged, list(fields_a ^ fields_b))
| improve this answer | |
  • I was thinking exactly along these lines, just hoped there would be a built in or more performant way to do something that I thought would be a pretty common operation. – Hugh_Kelley Sep 1 at 18:39
3

Creating layers with hidden fields is the way to go here, using field info objects. I have a function I regularly use for this. Then it's a matter of creating your two layers and using them as inputs in your merge.

Try:

import arcpy
fc1 = r"your\first\featureclass"
fc2 = r"your\second\featureclass"
mergeFc = r"your\output\merge\featureclass"

##function for creating layer with limited fields
def CreateFieldInfoLayer (fc, outLayer, flds, sql = None):
    """
    fc = input feature class
    outLayer = name of output layer
    flds = fields that will be visible in new layer
    sql = option where clause to apply to layer
    """
    #create layer with an unused name
    layer = "templayer"
    arcpy.MakeFeatureLayer_management (fc, layer)
    #get field info
    fldInfo = arcpy.Describe (layer).fieldInfo
    #set fields no in input list to hidden
    for i in range (fldInfo.count):
            fldName = fldInfo.getFieldName (i)
            if not fldName in flds:
                    fldInfo.setVisible (i, "HIDDEN")
    #create new layer with field info applied
    arcpy.MakeFeatureLayer_management (layer, outLayer, sql, None, fldInfo)
    #delete initial layer
    arcpy.Delete_management (layer)
    return outLayer

#get common fields
flds = [f.name for f in arcpy.ListFields (fc1)]
flds = [f.name for f in arcpy.ListFields (fc2) if f.name in flds]

#create layers with unshared fields hidden
lyr1 = CreateFieldInfoLayer (fc1, "lyr1", flds)
lyr2 = CreateFieldInfoLayer (fc2, "lyr2", flds)

#merge
arcpy.Merge_management(([lyr1, lyr2], mergeFc)
| improve this answer | |
  • if I export the layer, will the hidden fields be included? the goal of deleting the extra fields is to keep things clean for a later user when they export. – Hugh_Kelley Sep 1 at 18:04
  • 1
    If you export via copy features or similar tools only visible fields will be in your new feature class. – Emil Brundage Sep 1 at 18:05
0

so I just wanted to add the solution i ended up going with, a hybrid of a few different ones.

It's frustrating the the esri documentation for Merge_Management() doesn't actually say how it keeps/deletes fields but it will.

relevant code sample below.

pointfieldmappings = arcpy.FieldMappings()

point_keep_fields = ['RequestID','Prioritization_Bucket','Date_Initiated','Match_addr','X','Y',
                       'Description','Year','full_address','Sidewalk_Presence_Criteria',
                       'Bike_Network_Criteria','Lighting_Presence_Criteria','Equity_Criteria',
                       'City_Plans_Criteria','Crash_History_Criteria','Community_Requests_Criteria',
                       'Transit_Criteria','Functional_Classification_Criteria','Community_Center_Services_Criteria',
                       'Commercial_Retail_Criteria','Proximity_to_existing_speed_humps_Criteria','Senior_Center_Housing_Criteria','School_Zone_Criteria','Prioritization_Score','Priority_Bucket']
        
pointfieldmappings.addTable(point_table)
pointfieldmappings.addTable(point_master)
for field in pointfieldmappings.fields:
    if field.name not in point_keep_fields and not field.required:
                    pointfieldmappings.removeFieldMap(pointfieldmappings.findFieldMapIndex(field.name))
    
point_combined_results = point_table + "_all"
                        
arcpy.Merge_management(inputs = [point_table, point_master],
                                   output=point_combined_results,
                                   field_mappings=pointfieldmappings)

the point_keep_fields variable could also be built using the a_fields ^ b_fields code, but in my case that wasn't exactly what I needed.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.