1

I've cobbled together a script, part of which creates field mapping to sum fields in a spatial join. It took 13 lines of codes just to define which fields I want summed in the output. Is there a simpler/more elegant way to define and sum output fields?

import arcpy, os

ws = arcpy.GetParameterAsText(0)
ws2 = arcpy.GetParameterAsText(1)
outws = arcpy.GetParameterAsText(2)

arcpy.env.workspace = ws

# List all feature classes in ws
fcs = arcpy.ListFeatureClasses()

for fc in fcs:
    # Create full paths for pair1 and pair2
    pair1 = os.path.join(ws, fc)
    pair2 = os.path.join(ws2, fc)
    outfc = os.path.join(outws, "Joined_" + fc)


    #Create Field Mappings
    fieldMappings = arcpy.FieldMappings() #Create field mappings object

    fieldNamesToSum = ['Min_MA_NEW', 'Min_01_NEW', 'Min_02_NEW', 'Min_03_NEW', 'Min_04_NEW', 'Min_05_NEW', 'Min_06_NEW', 'Min_07_NEW', 'Min_08_NEW', 'Min_09_New', 'Min_10_NEW', 'Min_11_NEW', 'Min_12_NEW'] #Field names to sum

    # This creates a field mapping that only outputs the sums of the joined fields in fieldNamesToSum - the range number must equal the number of fields in fieldNamesToSum
    for i in range(13):
        fm_type = arcpy.FieldMap()
        fm_type.addInputField(pair2, fieldNamesToSum[i])
        outField = fm_type.outputField
        outField.name = fieldNamesToSum[i]
        fm_type.outputField = outField
        fieldMappings.addFieldMap(fm_type) #Sequentially add 13 FieldObjects
        fieldIndex = fieldMappings.findFieldMapIndex(fieldNamesToSum[i])
        fieldMap = fieldMappings.getFieldMap(fieldIndex) 
        fieldMap.mergeRule = 'Sum'
        fieldMappings.replaceFieldMap(fieldIndex, fieldMap)


    arcpy.SpatialJoin_analysis (pair1, pair2, outfc, "JOIN_ONE_TO_ONE", "KEEP_ALL", fieldMappings, "SHARE_A_LINE_SEGMENT_WITH")
  • 1
    Ugh. Field maps are the worst. I typically find it easier to do a series of intersections/unions/clips/merges--whatever you need--interspersed with cursors/calculations. – Tom Aug 10 '16 at 19:37
  • Take a look at gis.stackexchange.com/a/176016/64785 – Midavalo Aug 11 '16 at 4:18
  • For code review there is the Code Review Stack Exchange. – PolyGeo Feb 3 '18 at 8:11
0

I have not tested your code but it would seem to me that you could forget about your field mappings and simply run:

arcpy.SpatialJoin_analysis (pair1, pair2, outfc, "JOIN_ONE_TO_ONE", "KEEP_ALL", "#", "SHARE_A_LINE_SEGMENT_WITH")

(or the "series of intersections/unions‌​/clips/merges--whatev‌​er you need" mentioned in @Tom's comment)

then use the Summary Statistics tool on your outfc which:

Calculates summary statistics for field(s) in a table.

For any post-processing such as summing fields you could use arcpy.da.UpdateCursor().

  • The reason I am using field mapping is because there are about 100 fields in this person's join data, and they only need specific ones, but those fields must be summed since there are multiple records from pair2 that are being joined into pair1. – spaine Aug 17 '16 at 17:01
0

Building off of @PolyGeo's answer, I've developed a function that creates layers with only indicated fields visible. This will limit your geoprocessing tool's output fields.

import arcpy
import random
def CreateFieldInfoLayer (fc, flds, layerName, sql = None):
    """
    Creates a layer with only indicated fields visible
    fc = input feature class
    flds = python list of fields
    layerName = output layer name
    sql = sql to be applied to layer (optional)
    """

    #create layer with unique name
    layer = "lyr{}".format int ((random.random () * 100000))
    while arcpy.Exists (layer): layer = "lyr{}".format int ((random.random () * 100000))
    layer = arcpy.MakeFeatureLayer_management (fc, layer) [0]
    #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
    outLayer = arcpy.MakeFeatureLayer_management (fc, layerName, sql,
                                                  field_info = fldInfo) [0]
    #delete initial layer
    arcpy.Delete_management (layer)
    return outLayer

Example:

lyr2 = CreateFieldInfoLayer (pair2, fieldNamesToSum, "lyr2")

Now as PolyGeo suggested, spatially join.

arcpy.SpatialJoin_analysis (pair1, lyr2, outfc, "JOIN_ONE_TO_ONE", "KEEP_ALL", "#", "SHARE_A_LINE_SEGMENT_WITH")

The output feature class will be limited to the indicated fields from lyr2. Then summary statistics.

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.