5

I'm scripting a spatial join in ArcGIS with Python. I only want the resultant feature class to have a single field containing one attribute from the join features. In general, many join features overlap a single target feature and I want to preserve the attributes from all of them. I'm joining one-to-one, with the 'join' merge rule and a comma delimiter.

The problem arises when the new field exceeds 50 characters (the default) and the spatial join fails. I need to update the field's 'length' attribute, but I can't - if I assign a new value to it, nothing changes.

Here's a snippet that generates the field mapping object that I'll pass to spatial join:

# Generate a field mappings object and add the two join layers
fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable(outPolys)
fieldmappings.addTable(overlapping_SAs)

# facID_str is the field that we want
# Set its merge rule to 'join' and add a comma delimiter

# Get all field names from the join features
fnames = arcpy.ListFields(overlapping_SAs)

for field in fnames:
  if field.name == "facID_str":
    fidx = fieldmappings.findFieldMapIndex(field.name)
    fmap = fieldmappings.getFieldMap(fidx)

    # Set the merge rule to sum and update the object
    fmap.mergeRule = "join"
    fmap.joinDelimiter = ","

    fieldmappings.replaceFieldMap(fidx, fmap)

  # Delete all other fields
  else:
     fidx = fieldmappings.findFieldMapIndex(field.name)
     if fidx > 0:
       fieldmappings.removeFieldMap(fidx)

I can see the field I want by calling fieldmappings.fields[1].length but if I try to set the length to something other than 50, nothing happens. For example:

>>> fieldmappings.fields[1].length
50
>>> fieldmappings.fields[1].length = 500
>>> fieldmappings.fields[1].length
50

The eventual call to spatial join looks like this: arcpy.SpatialJoin_analysis(outPolys, overlapping_SAs, outJoin, "JOIN_ONE_TO_ONE", "KEEP_COMMON", fieldmappings, "WITHIN")

How do I set length to a value more appropriate for my application?

3

Looking at the help for fieldmappings the property fields returns a read only list of field objects I guess this is why its not working. You need to access the length property of the field object via the fieldmap object. Below is the corrected code:

import arcpy
fieldmappings = arcpy.FieldMappings()
fieldmappings.addTable("Catchment")
fieldmappings.addTable("Field Sites")
fnames = arcpy.ListFields("Field Sites")
for f in fnames:
    if f.name == "SiteLabel":
        print "DOING SITE LABEL!"
        fidx = fieldmappings.findFieldMapIndex(f.name)
        fmap = fieldmappings.getFieldMap(fidx)
        fmap.mergeRule = "join"
        fmap.joinDelimiter = ","

        ##### Here is how you change the field length of the output field
        theField = fmap.outputField
        theField.length = 1000
        fmap.outputField = theField
        #####

        fieldmappings.replaceFieldMap(fidx,fmap)
    else:
        print "DROPPING " + f.name
        fidx = fieldmappings.findFieldMapIndex(f.name)
        if fidx > 0:
            fieldmappings.removeFieldMap(fidx)


arcpy.SpatialJoin_analysis("Catchment", "Field Sites", "in_memory/xxx6", "JOIN_ONE_TO_ONE", "KEEP_COMMON", fieldmappings, "INTERSECT")
0

I just dealt with this issue yesterday, and found the AlterField_management tool to work. The ESRI help link is: https://desktop.arcgis.com/en/desktop/latest/tools/data-management-toolbox/alter-field-properties.htm

The sample code reads:

import arcpy

#Set local variables
fc = "C:/Data/Garbo.gdb/trails" #Note:empty feature class
field = "condition_rating" #short int, non nullable field
new_name = "notes"
new_alias = "Comments on Trail Condition"
new_type = "TEXT"
new_length = "60"
new_is_nullable = "NULLABLE"
clear_alias = "FALSE"

#Alter the properties of a non nullable, short data type field to become a text field
arcpy.AlterField_management(fc, field, new_name, new_alias, new_type, new_length, new_is_nullable, clear_alias)

If you precede your join with this table management you ought to be able to perform the join with wider fields.

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.