Summing but not all attributes during Spatial Join

4942
4
05-13-2014 01:26 PM
PolinaBerenstein
New Contributor
Hi, I am writing a script that is supposed to output an arithmetic function based on a spatial join of census tracts to a multipart buffer layer.

The function requires some census tract features summed (aka all tract populations within a buffer range get summed together) but other features to remain as attributes of that tract.

I have no experience with FieldMapping objects, and would like to start off by specifying which attributes get summed. Seems simple, but I have not found a template I can easily follow online, so.... any ideas?

I had originally assumed it would be as easy as simply setting the merge rule, but it seems that I would have to create a whole new object, and the ArcGIS help is very confusing for Field Mapping.
Tags (2)
0 Kudos
4 Replies
BradPosthumus
Occasional Contributor II
Field mapping isn't completely straight-forward but once you understand how to get started it's not too bad. The second code sample in the Spatial Join help explains how to set it up fairly well: http://resources.arcgis.com/en/help/main/10.1/index.html#//00080000000q000000

For your case, make a new field mapping object and populate it with the fields from the attribute tables. The field mapping object will now contain all of the field maps for your fields (using default values). Now you can pull out the field map for the field to sum, change the merge rule, then put it back in the field mapping object.

import arcpy
arcpy.env.overwriteOutput = True

targetFeatures = r'C:\data.gdb\bufferLayer'
joinFeatures = r'C:\data.gdb\censusTracts'
outputFeatures = r'C:\data.gdb\spatialJoinOutput'

# create a list of fields to sum
fieldNamesToSum = ['CENSUS_FIELD_TO_SUM_1', 'CENSUS_FIELD_TO_SUM_2']

# create the field mapping object
fieldMappings = arcpy.FieldMappings()

# populate the field mapping object with the fields from both feature classes
fieldMappings.addTable(targetFeatures)
fieldMappings.addTable(joinFeatures)

# loop through the field names to sum
for fieldName in fieldNamesToSum:

    # get the field map index of this field and get the field map
    fieldIndex = fieldMappings.findFieldMapIndex(fieldName)    
    fieldMap = fieldMappings.getFieldMap(fieldIndex)

    # update the field map with the new merge rule (by default the merge rule is 'First')
    fieldMap.mergeRule = 'Sum'

    # replace with the updated field map
    fieldMappings.replaceFieldMap(fieldIndex, fieldMap)

arcpy.SpatialJoin_analysis(targetFeatures, joinFeatures, outputFeatures, "JOIN_ONE_TO_ONE", "KEEP_ALL", fieldMappings, "INTERSECT", "", "")
PolinaBerenstein
New Contributor
Hi, thank you for the reply.

I understand how it should work theoretically in the code, but I have a lot of attributes so I wanted to try to do it through Model Builder to try an understand the syntax.

Currently I am just trying to sum all populations within each income category in census tracts if they fall within a buffer range.

Basically, i have a layer of buffers made from tract centroids, and I want each buffer to contain the sum of populations of all the tracts that intersect with it. I created the field map in model builder and set every property to "sum", but when I run the tool it still outputs just the unique value of the tract that the buffer was created from (centroid). Is it possible to get it to sum the underlying census tracts?? I thought that's what the sum function would do.
0 Kudos
BradPosthumus
Occasional Contributor II
You sound like you're on the right track so I'm not sure why it's not working. But maybe I'm missing something. Here's the steps I used in Model Builder that worked for me:


  1. Create a new model and add the Spatial Join tool from the "Analysis Tools-> Overlay" toolbox.

  2. Add the buffered centroids as the Target Features.

  3. Add the tract polygons as the Join Features.

  4. Join Operation is set to 'JOIN_ONE_TO_ONE'.

  5. In the 'Field Map of Join Features' it should list all of the fields from both the Target and Join features. For the Join feature fields only, right-click on the field name, select 'Merge Rule' and then 'Sum'.

  6. 'Match Option' should be set to INTERSECT.


Clicking OK returns a new buffered centroids layer that now contains fields with the summed values of the intersecting tract polygons. So if one buffered centroid feature intersects three tract features with populations of 1000, 2000, and 3000, the new buffered centroid feature has a population field with a value of 6000. I guessing this is the behaviour you're expecting.

Something I noticed in Model Builder, at least in 10.1: if you change the source of the Target or Join features, it doesn't update the field map section in the Spatial Join tool as it should. It will either keep fields from the previous feature classes or in some cases it will be completely blank. Deleting the spatial join tool from the model, adding it again, and then reconnecting the Target and Join features seems to fix this.
0 Kudos
DavidWasserman
Occasional Contributor III

I realize this is a little old, but I did write a variant of spatial join for the use case you are discussing. It can integrate into model builder workflows and the python sample is there. 

ArcNumerical-Tools/NumericalSpatialJoin.py at master · Holisticnature/ArcNumerical-Tools · GitHub 

Let me know if you have any questions. 

David Wasserman, AICP
0 Kudos