Spatial Join not populating

336
7
Jump to solution
07-22-2020 08:18 AM
2Quiker
Occasional Contributor II

I have two feature classes "Par" which is the large boundary(Red line) and "Par1" which is just parcels (black lines). The issues is I only get one single parcel populated with my current code. In the example attached, there are 6 parcels within the red boundary and I need all 6 of those parcels to be in the "PARCELS" field. I have the following code and on line 23 I have indicated that I want to use the Join as the merge rule. The "PARCEL" field on line 23 is the Data source field in Par1 that has each parcel. As far as the map options I have tried, INTERSECT, HAVE_THEIR_CENTER_IN, CONTAINS, WITHIN and it's the same results. I am assuming I am over looking something but I am not sure what it is...

import sys, arcpy, os, fnmatch
from arcpy import env
from datetime import datetime as d
startTime = d.now()
start_time = time.time()


print ('Started')
arcpy.env.overwriteOutput = True
arcpy.env.qualifiedFieldNames = False

arcpy.env.workspace = r"C:\Temp\Scratchworkspace.gdb"

fc_Delete = ["BlahTest"]

Par = "C:/Temp/Diss_Par.shp"
Par1 = "C:/Temp/Parcels.shp"

FieldMapString = '''

PIN "PIN" true true false 13 Text 0 0 ,First,#, {0}, PIN,-1,-1;
ACRES "ACRES" true true false 4 Double 0 0  ,First,#, {0}, ACRES,-1,-1;
PARCELS "PARCELS" true true false 200 Text 0 0 ,Join,#, {0}, PARCEL,-1,-1
'''

def Layers1(Par1):
    fieldmappings = arcpy.FieldMappings()
    fieldmappings.loadFromString(FieldMapString)
    return fieldmappings

def main(args=None):
        if args is None:
                args = sys.argv

arcpy.SpatialJoin_analysis(Par, Par1, "BlahTest", "JOIN_ONE_TO_ONE", "KEEP_ALL",Layers1(Par1), "HAVE_THEIR_CENTER_IN")
print (" Spatial Join Finished")
print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RandyBurton
MVP Regular Contributor

I took another look at your code and noticed the SpatialJoin is making a call to the Layers1 function for the field mapping.  It is being passed the Par1 variable, but the function is not using it.  This may be part of the problem.

While I don't completely understand field mapping, I did some testing and have the following test code that may be of help.  I created a block layer with an ID field called BLOCK.  I created a parcels layer with a text ID field called PIN.  (I don't like working with shape files, so I used a file geodatabase.  The joined layer, once created, could be dumped to a shape file.) The features and the join table created look like the following.

Spatial Join test

Here's my test code.  Hope it helps.

import arcpy

blocks = r"C:\Test\Test.gdb\test_blocks"
# only field used from blocks was the id field "BLOCK"
parcels = r"C:\Test\Test.gdb\test_parcels"
# only field used from parcels was the id field "PIN"
joined = r"C:\Test\Test.gdb\test_sj"
# the joined feature will also contain fields created during the spatial join

# use {0} for blocks and {1} for parcels in field mapping string
# for PIN field, parcels uses a text field of 12 characters, this was lengthened in the fms to 200
#   so the joined values would fit
fms = """
BLOCK "BLOCK" true true false 12 Text 0 0 ,First,#,{0},BLOCK,-1,-1;
PIN "PIN" true true false 200 Text 0 0 ,Join,",",{1},PIN,-1,-1
""".format(blocks, parcels)

arcpy.SpatialJoin_analysis(
    target_features = blocks,
    join_features = parcels,
    out_feature_class = joined,
    join_operation = "JOIN_ONE_TO_ONE",
    join_type = "KEEP_ALL",
    field_mapping = fms,
    match_option="INTERSECT",
    search_radius="",
    distance_field_name="")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

7 Replies
DavidPike
MVP Frequent Contributor

In the FielMapString, wher is the {0} coming from? It should reference the join feature path but I dont see your function doing what you're intending ( also why is the parameter already specified in the function definition?) or see the point of it other than confusing things.

Your delimiter is blank also.

0 Kudos
2Quiker
Occasional Contributor II

The {0} is the data source and in this case it would the data source to Par1 fields.

I did notice that the join delimiter was missing, I have since added ",".

PARCELS "PARCELS" true true false 10000 Text 0 0 ,Join,",", {0}, PARCEL,-1,-1‍
0 Kudos
2Quiker
Occasional Contributor II

I forgot to include Par1 "Parcel" field in the field mapping.

PARCEL "PARCEL" true true false 50 Text 0 0 ,First,"#",{0}, PARCEL,-1,-1;
PARCELS "PARCELS" true true false 7000 Text 0 0 ,Join,",",{0}, PARCEL,-1,-1
0 Kudos
DavidPike
MVP Frequent Contributor

I've never seen {0} in reference to passing the function parameter from an index.  Perhaps put some print statements in to see what is happening?

0 Kudos
RandyBurton
MVP Regular Contributor

It looks as if the {0} should be replaced with something via .format.  For example:

fc = r"C:\Path\To\File.gdb\feature"

FieldMapString = """PIN "PIN" true true false 13 Text 0 0 ,First,#, {0}, PIN,-1,-1;""".format(fc)

Print FieldMapString

# PIN "PIN" true true false 13 Text 0 0 ,First,#, C:\Path\To\File.gdb\feature, PIN,-1,-1;
‍‍‍‍‍‍‍
0 Kudos
RandyBurton
MVP Regular Contributor

I took another look at your code and noticed the SpatialJoin is making a call to the Layers1 function for the field mapping.  It is being passed the Par1 variable, but the function is not using it.  This may be part of the problem.

While I don't completely understand field mapping, I did some testing and have the following test code that may be of help.  I created a block layer with an ID field called BLOCK.  I created a parcels layer with a text ID field called PIN.  (I don't like working with shape files, so I used a file geodatabase.  The joined layer, once created, could be dumped to a shape file.) The features and the join table created look like the following.

Spatial Join test

Here's my test code.  Hope it helps.

import arcpy

blocks = r"C:\Test\Test.gdb\test_blocks"
# only field used from blocks was the id field "BLOCK"
parcels = r"C:\Test\Test.gdb\test_parcels"
# only field used from parcels was the id field "PIN"
joined = r"C:\Test\Test.gdb\test_sj"
# the joined feature will also contain fields created during the spatial join

# use {0} for blocks and {1} for parcels in field mapping string
# for PIN field, parcels uses a text field of 12 characters, this was lengthened in the fms to 200
#   so the joined values would fit
fms = """
BLOCK "BLOCK" true true false 12 Text 0 0 ,First,#,{0},BLOCK,-1,-1;
PIN "PIN" true true false 200 Text 0 0 ,Join,",",{1},PIN,-1,-1
""".format(blocks, parcels)

arcpy.SpatialJoin_analysis(
    target_features = blocks,
    join_features = parcels,
    out_feature_class = joined,
    join_operation = "JOIN_ONE_TO_ONE",
    join_type = "KEEP_ALL",
    field_mapping = fms,
    match_option="INTERSECT",
    search_radius="",
    distance_field_name="")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
2Quiker
Occasional Contributor II

I have a hard time understanding field mapping as well, I don't like it.

0 Kudos