Saturday, 24 March 2018

Scripting spatial join in ArcPy to set field attribute in field mapping object?



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?




Answer



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

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...