Update features with multiple values, Spatial Join or Select by Location Or Dictionaries

1075
15
Jump to solution
07-28-2020 10:50 AM
2Quiker
Occasional Contributor II

I have a hard time with field mapping and the only form I seem to understand is the following but it also seems to not work, maybe I doing it wrong but here is what I found. Using a code like below

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;
PARCEL "PARCEL" true true false 50 Text 0 0 ,First,"#",{0}, PARCEL,-1,-1;
PARCELS "PARCELS" true true false 200 Text 0 0 ,Join,",", {1}, PARCEL,-1,-1‍‍‍

arcpy.SpatialJoin_analysis(Par, Par1, "BlahTest", "JOIN_ONE_TO_ONE", "KEEP_ALL",Layers1(Par1), "INTERSECT")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

I found that the output had 19 parcels inside the "PARCELS" field and it looked incorrect. So I opened up Arcmap and used select by location with the same spatial selection method "intersect" and selected 25. So I would like to use spatial join with Dictionaries or Select By Location if possible but my problem is how to use the merge rule and delimiter to update the fields. How would I apply the code I am using to use Dictionaries or Select By Location?

Outcome of field PARCELS should be something like the following.

PIN12345,PIN12346,PIN12347, PIN12348, etc.

arcpy.SpatialJoin_analysis(updateFC, Par, sj, "JOIN_ONE_TO_ONE", "KEEP_ALL")

# define the field list from the spatial join
sourceFieldsList = ["TARGET_FID", "Parcel_1"]    

# define the field list to the original Parcels
updateFieldsList = ["OID@", "PARCELS"]

# populate the dictionary from the polygon
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sj, sourceFieldsList)}    

with arcpy.da.UpdateCursor(updateFC, updateFieldsList) as updateRows:    
    for updateRow in updateRows:    
        keyValue = updateRow[0]    
        if keyValue in valueDict:    
            for n in range (1,len(sourceFieldsList)):      
                updateRow[n] = valueDict[keyValue][n-1] #How do update the field to include multi values from the selection by location?
            updateRows.updateRow(updateRow)    

    del valueDict‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

targetLayer = "In_memory\tempTarget"
arcpy.MakeFeatureLayer_management(target, targetLayer)

MergetLayer = "In_memory\tempMerge"
arcpy.MakeFeatureLayer_management(Merge2,MergetLayer)
with arcpy.da.SearchCursor(Merge2,["SHAPE@", "PARCEL"]) as cursorSearch:
    for row in cursorSearch:       
        arcpy.SelectLayerByLocation_management (targetLayer, "INTERSECT", row[0])       
        with arcpy.da.UpdateCursor(targetLayer,["SHAPE@", "PARCELS"]) as cursorUpdate:
            for row2 in cursorUpdate:
                row2[1] = row[1] #How do update the field to include multi values from the selection by location?
                cursorUpdate.updateRow(row2)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RandyBurton
MVP Regular Contributor

Thanks for sharing some sample data.  I used nested cursors for a quick test and noticed that several of the buildoutPolygons contained a large number of parcels.  If you concatenated the parcel id numbers, you would end up with a string much longer than the field length of 250 characters allowed with a shapefile.  In addition, some of the polygons appear complex (multipart and non-contiguous) , which might indicate some other issues.  Here is screenshot showing one selected polygon feature that has 66 parcels located in it.

One selected polygon showing it contains 66 parcels.

Here is the test script:

polygons = 'buildoutPolygons1'
parcels = 'buildoutParcels1'

# clear all selected features
arcpy.SelectLayerByAttribute_management(polygons, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")

with arcpy.da.UpdateCursor(polygons, ['SHAPE@', 'OID@', 'PAR_COUNT', 'PARCELS']) as cursor:
    for row in cursor:
        arcpy.management.SelectLayerByLocation(parcels, "HAVE_THEIR_CENTER_IN", row[0], "", "NEW_SELECTION")
        par_count = int(arcpy.GetCount_management(pars)[0]) # parcel count
        # get list of parcel id numbers
        pins = []
        with arcpy.da.SearchCursor(parcels, ['PARCEL']) as parcelsCursor:
            for parcelRow in parcelsCursor:
                pins.append(parcelRow[0]) # save PIN in pins list
        # print for testing
        print row[1], par_count # OID@ and count
        print ','.join(pins) # parcel ids in polygon
        print
        # update row
        row[2] = par_count
        # row[3] = ','.join(pins) # not updated as some results longer than field width
        cursor.updateRow(row)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The single polygon from the photo, FID = 34, gave the following results:

34 66
R3590700000,R3590701000,R3590801000,R3590900000,R3591800000,R3594801100,R3595100000,R3595500000,R3595500000,R35957010A0,
R3595901000,R3596001000,R3596001100,R3596800000,R3596801000,R3597200000,R3597301000,R3597500000,R3597700000,R3597701000,
R3598101100,R3598200000,R3598500000,R3598901100,R3599600000,R3599900000,R3600101000,R3600101100,R3600500000,R3601200000,
R3601300000,R3601500000,R3601900000,R3602100000,R3602401000,R3602600000,R3602701200,R3602901000,R3603500000,R3603600000,
R3603700000,R3604000000,R3604301000,R3604900000,R3605100000,R3605200000,R3605201000,R3606400000,R3606400000,R3606401000,
R3606401000,R3606500000,R3606500000,R3606600000,R3606800000,R3607600000,R3607800000,R3607900000,R3608000000,R3608100000,
R3608301000,R3609601000,R3609801300,R3610000000,R3610101000,R3610200000

Hope this helps.

View solution in original post

0 Kudos
15 Replies
RandyBurton
MVP Regular Contributor

Can you share the field layout of the two features that are being joined with, perhaps, some sample data?  It would be helpful in understanding what needs to be done.

0 Kudos
2Quiker
Occasional Contributor II

Sure thing, thanks.

I need to populate the Buildout polygons "Parcels" field with the parcels numbers from the BuildoutParcels "Parcel" field that have their center in each Buildout Polygon.

With spatial join using HAVE_THEIR_CENTER_IN, I just get one parcel that is populated. I don't need to use interest because it will grab parcels that are not within the buildout polygon.

0 Kudos
NicholasKlein-Baer
New Contributor III

I'm having a hard time following what is going on in those three code chunks.

But maybe try something like this 

```

# do the spatial join with the 'buildoutParcels' as the Target Features and the 'buildoutPolygons' as the Join features
# One to many may not be necessary, as it looks like each parcel only pertains to one buildoutpoly
# Keep common makes it easier in the next step by not including parcels that don't have a center within ANY buildoutpoly

buildoutParcels = r"PATH\TO\YOUR\DATA\buildoutParcels1.shp"  #or reference to layer
buildoutPolygons = r"PATH\TO\YOUR\DATA\buildoutPolygons1.shp"
joinOutput = r"PATH\TO\YOUR\DATA\spatialJoin.shp"

arcpy.analysis.SpatialJoin(buildoutParcels, buildoutPolygons , joinOutput, "JOIN_ONE_TO_MANY", "KEEP_COMMON", '', "HAVE_THEIR_CENTER_IN")

#create a dictionary to hold list of parcels w/ FID of buildoutPolygon features as key
parcel_dict = {}
with arcpy.da.SearchCursor(joinOutput , ['JOIN_FID','PARCEL']) as cursor:
    for row in cursor:
        parcels = parcel_dict.get(row[0])
        if not parcels:
            parcels = [row[1]]
        else:
            parcels.append(row[1])
         parcel_dict.update({row[0]:parcels})

#use this dict to update the buildoutPolygons FC (maybe a good idea to make a copy and update that instead of original?)
with arcpy.da.UpdateCursor(buildoutPolygons,['FID','PARCELS']) as cursor:
    for row in cursor:
        row[1] = " , ".join(parcel_dict[row[0]])
        cursor.updateRow(row)

```

2Quiker
Occasional Contributor II

Sorry I was just putting up some examples of using select by location and dictionaries because the spatial join with field mapping wasn't giving me the results I wanted.

I am getting error on "row[1] = " , ".join(parcel_dict[row[0]])".

 row[1] = " , ".join(parcel_dict[row[0]])
KeyError: 0

changed it to

row[1] = " , ".join(parcel_dict[row[1]])
        cursor.updateRow(row)

Error;    

row[1] = " , ".join(parcel_dict[row[1]])
KeyError: 'R0021300000

0 Kudos
NicholasKlein-Baer
New Contributor III

The dictionary is set up using the FID's of the buildoutPolygon features as the keys, so trying to use the value of the 'PARCELS' field  as a key (i.e. changing it to parcel_dict[row[1]] ) is not going to work. 

It looks like there is no entry in the dictionary for the feature with FID 0. Try printing out the dictionary before running the update cursor to check that it has been properly populated. 

2Quiker
Occasional Contributor II

I was able to to.
I moved the layers into a field geodatabase.

I changed Join_FID to Target_FID as it seems that is the key fields.

{4: ['R0020500000'], 3622: ['R0046400000', 'R0067800000'], 12: ['R0113600000'], 15: ['R0157600000'], 25: ['R0204200000'], 43: ['R0218600000', 'R0218601000'], 49: ['R0227200000'], 130: ['R0710600000'], 181: ['R0891500000'], 188: ['R0899500000'], 6708: ['R0966500000'], 6709: ['R0966500000'], 269: ['R1304600000'], 286: ['R1327000000'], 287: ['R1327300000'], 320: ['R1355800000'], 323: ['R1356900000'], 324: ['R1357500000'], 325: ['R1357700000'], 326: ['R1358800000'], 348: ['R1394100000'], 355: ['R1399500000'], 377: ['R1428553000'], 402: ['R1503820200', 'R1503822200'], 425: ['R1542701200'], 458: ['R1578701000'], 475: ['R1593100000'], 483: ['R1607200000'], 497: ['R1619100000'], 512: ['R1760701100'], 513: ['R17607037B0'], 5700: ['R1797200000', 'R3456100000'], 539: ['R1896001000'], 540: ['R1897700000'], 548: ['R1922100000'], 616: ['R2007500000'], 617: ['R2007701000'], 1721: ['R2045100000'], 673: ['R2066500000'], 703: ['R2097300000'], 740: ['R2158100000'], 3845: ['R2163100000'], 791: ['R2202600000'], 792: ['R2202801100'], 793: ['R2202900000', 'R2202901000'], 794: ['R2202900000'], 787: ['R2203000000'], 805: ['R2204800000'], 814: ['R2207200000'], 820: ['R2208701000'], 822: ['R2208701000'], 824: ['R2208900000'], 827: ['R2209200000'], 832: ['R2209600000'], 835: ['R2209601000'], 867: ['R2264800000'], 912: ['R2287300000'], 921: ['R2287700000'], 922: ['R2288000000'], 930: ['R2288100000'], 959: ['R2289300000', 'R2287600000'], 3510: ['R2293801100'], 1030: ['R2359100000'], 1033: ['R2368300000'], 1037: ['R2378550200'], 1066: ['R2418300000'], 1983: ['R2419050600'], 1086: ['R2436400000'], 3921: ['R2455200000'], 1141: ['R2508300000'], 1211: ['R2552700000'], 1226: ['R2552800000'], 1231: ['R2615700000'], 4006: ['R2616100000'], 1236: ['R2617800000'], 1237: ['R2618300000'], 1238: ['R2624700000'], 5495: ['R2624900000'], 1284: ['R2745200000'], 1291: ['R2746100000'], 1293: ['R2747500000'], 1294: ['R2747500000'], 1296: ['R2760300000'], 1348: ['R2798300000'], 1418: ['R2798401100'], 1356: ['R2819200000'], 1359: ['R2822401000'], 1360: ['R2823001100'], 1361: ['R2823300000'], 1413: ['R2850600000'], 1414: ['R2851100000'], 1415: ['R2851600000'], 1416: ['R2854700000'], 1420: ['R2855601000'], 1438: ['R2866700000'], 1440: ['R2868101200'], 1441: ['R2875102500'], 1442: ['R2875300000'], 1443: ['R2876801200'], 1626: ['R2950101400'], 1778: ['R2991300000'], 1815: ['R3006100000'], 1831: ['R3028200000'], 1847: ['R3036001000', 'R3036301000'], 1848: ['R3036400000'], 1851: ['R3036901000'], 1852: ['R3037000000'], 1853: ['R3037200000'], 1858: ['R3038900000'], 1860: ['R3039300000'], 1867: ['R3041100000'], 1872: ['R3041400000'], 1874: ['R3042900000'], 1881: ['R3043501200'], 4763: ['R3045700000', 'R3045701100'], 4805: ['R30530010A0'], 2036: ['R3073200000'], 2053: ['R3077200000'], 4837: ['R3077200000', 'R3076200000'], 4847: ['R3081000000', 'R3080701000'], 2081: ['R3083100000'], 2123: ['R3093700000'], 2129: ['R3093900000'], 2134: ['R3095100000'], 2138: ['R3095200000'], 2154: ['R3097401000'], 2157: ['R3105301000'], 4948: ['R3106100000'], 2253: ['R3180000000'], 2264: ['R3183100000'], 2277: ['R3211700000'], 2301: ['R32229012A0'], 2326: ['R3232200000'], 2327: ['R3233701200'], 2341: ['R3239201000'], 2348: ['R3241400000'], 5076: ['R3243000000', 'R3243100000'], 2359: ['R3243400000'], 2360: ['R3243500000'], 3981: ['R3243700000'], 2371: ['R3255200000'], 2374: ['R3255200000'], 2375: ['R3256901000'], 2436: ['R32707010B0'], 5190: ['R3270900000', 'R3279101000'], 2463: ['R3278400000'], 2464: ['R3278400000'], 2465: ['R3278500000'], 2484: ['R3282801000'], 2486: ['R3284601000'], 2510: ['R3297500000'], 2541: ['R3314500000'], 2542: ['R3315100000'], 2544: ['R3315700000'], 2546: ['R3316900000'], 2547: ['R3319400000'], 5342: ['R3321501100'], 2565: ['R3341900000'], 2567: ['R3344500000'], 6736: ['R3346100000'], 6737: ['R3346100000'], 5374: ['R3346600000'], 2572: ['R3360200000'], 2575: ['R3373701300'], 5448: ['R3393800000'], 2624: ['R3395700000'], 2626: ['R3395800000'], 2627: ['R3396201000'], 5454: ['R3396201100'], 6738: ['R3398100000', 'R3398801200'], 6739: ['R3398100000', 'R3398801200'], 5452: ['R3398100000'], 2637: ['R3398800000'], 6742: ['R3398801000', 'R3398801000'], 6743: ['R3398801000', 'R3398801000'], 6792: ['R3398801000'], 6793: ['R3398801000'], 6746: ['R3398801100'], 6747: ['R3398801100'], 2639: ['R3398801100'], 2642: ['R3399700000'], 2671: ['R3408701100'], 2674: ['R3408901000'], 2676: ['R3409900000'], 2677: ['R3411700000'], 2678: ['R3411800000', 'R3411800000'], 2682: ['R3413200000'], 5497: ['R3413600000', 'R3413701000'], 2693: ['R3415400000'], 2696: ['R3415500000'], 2701: ['R3417000000'], 2702: ['R3417500000'], 2703: ['R3417700000'], 2705: ['R3417901000'], 2710: ['R3419400000'], 2712: ['R3420000000'], 2715: ['R3420501000'], 2716: ['R3420700000'], 2717: ['R3420800000'], 2725: ['R3421201100'], 2727: ['R3422200000'], 5550: ['R3422300000'], 2736: ['R3423700000'], 5559: ['R3424000000'], 2745: ['R3425601000'], 2746: ['R3425700000'], 2748: ['R34261010B0'], 2754: ['R3426300000'], 2756: ['R3427000000'], 2758: ['R3427301000'], 2763: ['R3428900000'], 2764: ['R3429500000'], 5597: ['R3429700000'], 2781: ['R3432901100'], 5617: ['R3433001000', 'R3432901000'], 2786: ['R3433800000'], 2787: ['R3434001600'], 2788: ['R3434501000'], 2790: ['R3435001000'], 5562: ['R3436900000'], 2842: ['R3445800000'], 2843: ['R3445800000'], 2844: ['R3445900000'], 2851: ['R3446200000'], 5687: ['R3449400000'], 2878: ['R3454600000'], 2881: ['R3457800000'], 2885: ['R3462200000'], 2901: ['R3473300000'], 2903: ['R3473701000'], 2904: ['R3473701200'], 2910: ['R3473701200'], 5749: ['R3474000000', 'R3474100000'], 2924: ['R3474601000', 'R3478500000'], 2936: ['R3514000000'], 2937: ['R3514101100', 'R3513901000'], 2938: ['R3514200000'], 2970: ['R3535300000', 'R3540400000'], 2972: ['R3547100000'], 2973: ['R3547100000'], 2974: ['R3547200000'], 2987: ['R3547500000'], 2988: ['R3552100000'], 2991: ['R3554600000'], 5890: ['R3555200000'], 3018: ['R3566100000'], 3031: ['R3577201000'], 3032: ['R3582300000'], 4018: ['R3582900000'], 3036: ['R3584000000'], 3037: ['R3585200000'], 5942: ['R3592200000'], 3057: ['R3600000000'], 3058: ['R3601400000'], 3065: ['R3602300000'], 3066: ['R3602300000'], 3067: ['R3602401100'], 5977: ['R3602601000'], 3084: ['R3608600000'], 3085: ['R3608600000'], 3086: ['R3608601000'], 3090: ['R3608900000'], 3097: ['R3610100000'], 3098: ['R3610100000'], 3100: ['R3610302000'], 6006: ['R3610302000'], 3106: ['R3612300000'], 6060: ['R3614700000'], 3125: ['R3627000000'], 6073: ['R3627700000'], 3141: ['R36327011A0'], 3160: ['R3639400000'], 3161: ['R3639400000'], 3163: ['R3639800000'], 3165: ['R3643000000'], 3166: ['R3643900000'], 3167: ['R3644100000'], 3168: ['R3644400000'], 3169: ['R3644800000'], 3170: ['R3644800000'], 6143: ['R3645000000', 'R3645900000'], 6144: ['R3645500000', 'R36459010A0'], 3180: ['R3646700000'], 3186: ['R3650500000'], 6158: ['R3650900000'], 3193: ['R3661500000'], 3197: ['R3665700000'], 6207: ['R3666600000'], 3205: ['R3672200000'], 6292: ['R3675500000', 'R3681100000', 'R3681301000'], 6320: ['R3690600000'], 3224: ['R3691500000'], 3237: ['R3701500000'], 3238: ['R3703200000'], 3242: ['R3705500000'], 3243: ['R3708100000'], 3245: ['R3710800000'], 6379: ['R3712400000', 'R3710600000'], 3250: ['R3713200000'], 3252: ['R3713700000'], 3253: ['R3716800000'], 3255: ['R3723800000'], 6415: ['R3723900000'], 6423: ['R3725100000'], 6440: ['R3729700000'], 3268: ['R3733400000'], 3272: ['R3739500000'], 3273: ['R3739700000'], 3274: ['R3739901000'], 3275: ['R3740000000'], 3278: ['R3743101000'], 3302: ['R3764000000'], 6549: ['R3765100000'], 3305: ['R3765400000'], 6554: ['R3765900000'], 3310: ['R3770100000'], 6560: ['R3770200000'], 3320: ['R3778200000'], 3321: ['R3780101000'], 6595: ['R3782700000'], 3330: ['R3787201000'], 3349: ['R3801301100'], 3353: ['R38056010A0'], 3354: ['R3807100000'], 3355: ['R3808301000'], 3356: ['R3808400000'], 3357: ['R3808900000'], 3363: ['R3809100000'], 3387: ['R3824900000'], 3394: ['R3827701000'], 3397: ['R3827800000'], 3399: ['R3829000000'], 3400: ['R3829200000'], 3401: ['R3829400000'], 3404: ['R3831500000'], 3409: ['R38329010A0'], 3411: ['R3833800000'], 3419: ['R3837400000'], 3422: ['R3839001000'], 3427: ['R3839800000'], 3432: ['R3845400000'], 3435: ['R3846000000'], 3452: ['R3857600000'], 3455: ['R3858901000'], 3456: ['R3858901000'], 3477: ['R3869700000'], 3485: ['R3873100000'], 3515: ['R3890200000'], 3516: ['R3890200000'], 3523: ['R3895900000'], 3525: ['R3896600000'], 3538: ['R3917501200'], 3544: ['R3925400000'], 3542: ['R3926700000'], 3553: ['R3931600000'], 3554: ['R3932500000'], 3564: ['R3940800000'], 3575: ['R3944600000'], 5482: ['R3279900000', 'R3408801000'], 3605: ['R3060801000'], 3606: ['R3407700000'], 3618: ['R0063200000'], 3626: ['R0111300000'], 3628: ['R0132700000'], 3629: ['R0133100000'], 3637: ['R0201300000'], 3640: ['R0214701000'], 45: ['R0221400000'], 3665: ['R0263101000'], 3674: ['R0455700000'], 3679: ['R0573200000'], 3682: ['R0586600000'], 3683: ['R0586600000'], 3704: ['R0971300000'], 3709: ['R1270700000'], 3710: ['R1272900000'], 3719: ['R1325201000'], 3720: ['R1334300000'], 3742: ['R14485010A0'], 3743: ['R1449800000'], 3746: ['R1489900000'], 3747: ['R1497701000'], 3748: ['R15038208A0'], 3752: ['R15038241B0'], 3753: ['R1503824700'], 3763: ['R1594200000'], 3764: ['R1600100000'], 3775: ['R17610010A0', 'R3475101000'], 3776: ['R1786700000'], 5718: ['R1817400000'], 3579: ['R2007600000'], 3828: ['R2045200000'], 3830: ['R2046800000'], 3838: ['R2114000000'], 1896: ['R2155700000'], 3850: ['R2201000000'], 815: ['R2202501200'], 3853: ['R2216400000'], 4853: ['R2239301000'], 3983: ['R2534301400'], 3527: ['R2540400000'], 4024: ['R2760800000'], 4235: ['R2786600000'], 4230: ['R2859901000'], 4240: ['R2860000000'], 4258: ['R2866500000'], 4266: ['R28685001A0'], 4150: ['R2874801000'], 4419: ['R2923701000'], 4422: ['R2924201200'], 4500: ['R29583012A0'], 4501: ['R2958800000'], 4502: ['R2958800000'], 4739: ['R3039500000'], 4748: ['R3040900000'], 4757: ['R3043400000'], 4764: ['R3047200000'], 4769: ['R3050400000'], 4799: ['R3060601200'], 1973: ['R3061200000'], 4809: ['R30666011A0'], 4829: ['R3073500000'], 4831: ['R3075100000'], 4832: ['R3076200000'], 4848: ['R3082601300'], 4855: ['R3086700000'], 4860: ['R3087000000'], 4874: ['R30926010A0'], 4900: ['R3093200000'], 4904: ['R3101401100'], 4913: ['R3101501000'], 4922: ['R31053011B0'], 4925: ['R3105701200'], 4928: ['R3106101000'], 2243: ['R3154301000'], 5018: ['R3180101000'], 5025: ['R3202901000'], 5028: ['R3203000000'], 5029: ['R3204401500'], 5042: ['R3206300000'], 5048: ['R32098010A3'], 5052: ['R3212101000'], 5069: ['R3239100000'], 5073: ['R3239200000'], 5075: ['R3239601000'], 5093: ['R3255000000'], 5094: ['R3255500000'], 5095: ['R3255500000'], 5097: ['R3255501100'], 5098: ['R3255501200'], 5099: ['R3255601000'], 5102: ['R3256100000'], 5104: ['R3258200000'], 5138: ['R3258500000'], 5154: ['R3268600000'], 5173: ['R3273700000'], 5174: ['R3274400000'], 5176: ['R3274500000'], 5193: ['R3279701000'], 5201: ['R32822011A0'], 5206: ['R32822011A0'], 5207: ['R3282700000'], 5304: ['R3314400000'], 5306: ['R3314600000'], 5308: ['R3315401100'], 5314: ['R3316300000'], 5318: ['R3319100000'], 5319: ['R3320000000'], 5320: ['R3320101000'], 5322: ['R3320101100'], 5323: ['R3320301000'], 5416: ['R3379000000'], 5443: ['R3392200000'], 5447: ['R33937010A0'], 6790: ['R3398801200'], 6791: ['R3398801200'], 5458: ['R3399901200'], 5476: ['R3407000000'], 5483: ['R3409200000'], 2672: ['R3409500000'], 5492: ['R3413000000'], 5493: ['R3413400000'], 5500: ['R3414000000'], 5501: ['R3414201000'], 5504: ['R3414301100', 'R3441900000'], 5517: ['R3416901000'], 5518: ['R3416901000'], 5519: ['R3416901200'], 5527: ['R3417600000'], 5531: ['R3420500000'], 5535: ['R3420701000'], 5539: ['R3421001000'], 5540: ['R3421201000'], 5543: ['R3422100000'], 5544: ['R3422100000'], 5545: ['R3422301200'], 5555: ['R34223012A0'], 5568: ['R3426201100'], 5571: ['R3426500000'], 5574: ['R3428500000'], 5575: ['R3428500000'], 5578: ['R3428600000'], 5580: ['R3428600000'], 5586: ['R3428700000'], 5592: ['R3428800000'], 5605: ['R3431201000'], 5606: ['R3431301000'], 5608: ['R3431501000'], 5615: ['R3432900000'], 5616: ['R3432901000'], 5618: ['R3433201000'], 5619: ['R3433201000'], 5620: ['R3433300000'], 5621: ['R3433300000'], 5623: ['R3433600000'], 5625: ['R3434001400'], 5652: ['R3441001000'], 5656: ['R3441501200'], 5657: ['R3441900000'], 5683: ['R3448401000'], 5684: ['R3448401000'], 5685: ['R3448500000'], 5704: ['R3449901100'], 5736: ['R3465300000'], 2893: ['R3465300000'], 5769: ['R34944010F1'], 5770: ['R3494901400'], 5771: ['R34949014A0'], 5781: ['R3497300000'], 5789: ['R3503700000'], 5801: ['R3512901400'], 5804: ['R3513600000'], 5825: ['R3527600000'], 5830: ['R3528401000'], 5831: ['R3528401000'], 5859: ['R3546700000'], 5860: ['R3546700000'], 5864: ['R3549800000'], 5872: ['R3549800000'], 5892: ['R3562301000'], 5893: ['R3563401100'], 5894: ['R3565601000'], 5899: ['R3568200000'], 5905: ['R3573000000'], 5908: ['R3573501000'], 5913: ['R3576500000'], 5916: ['R3577400000'], 5921: ['R35796011A0', 'R3582500000'], 5929: ['R35826011A0'], 6001: ['R3610301000'], 6002: ['R3610301000'], 6003: ['R36103010A0'], 6007: ['R36103010A0'], 6012: ['R3612400000'], 3110: ['R3612901100'], 6022: ['R3613301000'], 6025: ['R3613500000'], 6026: ['R3613600000'], 6027: ['R3613600000'], 6036: ['R3613700000'], 6076: ['R3630000000'], 6077: ['R3630100000'], 6078: ['R3630201100'], 6079: ['R3630201100'], 6082: ['R3631400000'], 6092: ['R3633000000'], 6095: ['R3634100000'], 6096: ['R3634100000'], 6107: ['R3637300000'], 6111: ['R3637301000'], 6113: ['R3637800000'], 6114: ['R3637800000'], 6115: ['R3637801100'], 6121: ['R3637801100'], 6123: ['R3639500000'], 6125: ['R3639900000'], 6127: ['R3639900000'], 6131: ['R3640101100'], 6134: ['R3642200000'], 6138: ['R3645101000'], 6142: ['R3645600000'], 6145: ['R3646000000'], 3175: ['R3646101000'], 6149: ['R3646701000'], 6150: ['R36467011A0'], 6151: ['R36468010A0'], 6152: ['R3647001200'], 6154: ['R3647800000'], 6165: ['R3650200000'], 6166: ['R3651201000'], 6174: ['R3653501000'], 6180: ['R3656800000'], 6181: ['R3657000000'], 6182: ['R3657000000'], 6185: ['R3657501000'], 6190: ['R36578010A0'], 6193: ['R3661600000'], 6253: ['R3675400000'], 6255: ['R3676200000', 'R3677000000'], 6259: ['R3676401100'], 6273: ['R3677601000'], 6282: ['R3678200000', 'R3679300000'], 6279: ['R3678700000'], 3216: ['R3679501000'], 6297: ['R3682300000'], 6307: ['R3682600000'], 6338: ['R3701400000'], 6340: ['R3702500000'], 6343: ['R3703401000'], 6346: ['R3704701000'], 6349: ['R37055010B0'], 6350: ['R37055010B0'], 6351: ['R3705800000'], 6354: ['R3705800000'], 6360: ['R3707900000'], 6371: ['R3710501200'], 6386: ['R3713100000'], 6391: ['R3713800000'], 6645: ['R3716300000']}
Traceback (most recent call last):

    row[1] = ','.join(parcel_dict[row[0]])
KeyError: 1
‍‍‍‍‍‍‍‍‍‍‍

joinOutput = r"C:\Temp\New File Geodatabase.gdb\sj"
arcpy.analysis.SpatialJoin(buildoutPolygons, buildoutParcels , joinOutput, "JOIN_ONE_TO_MANY", "KEEP_COMMON", '', "HAVE_THEIR_CENTER_IN")

 

#create a dictionary to hold list of parcels w/ FID of buildoutPolygon features as key
parcel_dict = {}
with arcpy.da.SearchCursor(joinOutput , ['JOIN_FID','PARCEL']) as cursor:
    for row in cursor:
        parcels = parcel_dict.get(row[0])
        if not parcels:
            parcels = [row[1]]
        else:
            parcels.append(row[1])
        parcel_dict.update({row[0]:parcels})

 
print (parcel_dict)
#use this dict to update the buildoutPolygons FC (maybe a good idea to make a copy and update that instead of original?)
with arcpy.da.UpdateCursor(buildoutPolygons,['OBJECTID_1','PARCELS']) as cursor:
    for row in cursor:
        row[1] = ','.join(parcel_dict[row[0]])
        cursor.updateRow(row)

0 Kudos
NicholasKlein-Baer
New Contributor III
I changed Join_FID to Target_FID as it seems that is the key fields.

It doesn't look like you actually did ... line 8 of your code still has 'JOIN_FID', and if you look at the output of your printed dictionary you can see that the keys match with 'JOIN_FID'.  But that's OK, you don't need to change it.

Your problem is that you swapped the polygons and the parcels in the spatial join from how I had it in my example.  It's a bit counter intuitive, but you need to use the parcels as the target FC and the polys as the join FC in order for the "HAVE_THEIR_CENTER_IN" join type to work here. So just switching the polygons and parcels in the original spatial join operation should get you past that key error (at least it does for me, using your example data)

The other issue, is that, as Randy mentioned, some of the polygons contain too many parcels to fit in a single field (max 250 char).  One way to do that would be to just make as many fields as you need, see below. Probably not the cleanest way, but seems to work

joinOutput = "join"
arcpy.analysis.SpatialJoin( buildoutParcels , buildoutPolygons, joinOutput, "JOIN_ONE_TO_MANY", "KEEP_COMMON", '', "HAVE_THEIR_CENTER_IN")


#create a dictionary to hold list of parcels w/ FID of buildoutPolygon features as key
parcel_dict = {}
with arcpy.da.SearchCursor(joinOutput , ['JOIN_FID','PARCEL']) as cursor:
    for row in cursor:
        parcels = parcel_dict.get(row[0])
        if not parcels:
            parcels = [row[1]]
        else:
            parcels.append(row[1])
        parcel_dict.update({row[0]:parcels})

print(parcel_dict)

#find the length of longest parcel list https://stackoverflow.com/a/21839239/11434833    
max_parcels = max(parcel_dict, key=lambda x: len(parcel_dict[x]))

# figure out how many fields you need @ 10 parcels per field
import math
n_fields = int(math.ceil(max_parcels/10)) 

# Create that new many fields .... 
new_fields_list = [] 
for i in range(0,n_fields):
    new_field_name = "PARCEL_" + str(i)
    arcpy.AddField_management(buildoutPolygons, new_field_name, "TEXT")
    new_fields_list.append(new_field_name)

#use this dict to update the buildoutPolygons FC (maybe a good idea to make a copy and update that instead of original?)
new_fields_list.insert(0,'OBJECTID_1')
print(new_fields_list)
with arcpy.da.UpdateCursor(buildoutPolygons,new_fields_list) as cursor:
    for row in cursor:
	print(row)
	for i in range(1,len(row)):
            row[i] = ','.join(parcel_dict[row[0]][i*10:i*10+10])
        cursor.updateRow(row)
0 Kudos
2Quiker
Occasional Contributor II

I am not sure what I am doing wrong on my end, have made the "PARCELS" field length 10,000. I have tried putting the layers in a .gdb and just a shapefile but always get an Key Error.

KeyError: 1

import arcpy
from arcpy import env
from datetime import datetime as d
startTime = d.now()
start_time = time.time()


print ('Started')

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


buildoutParcels = r"C:\Temp\Scratchworkspace.gdb\buildoutParcels1A"
buildoutPolygons = r"C:\Temp\Scratchworkspace.gdb\buildoutPolygons1A"

joinOutput = r"C:\Temp\Scratchworkspace.gdb\sj"
arcpy.analysis.SpatialJoin(buildoutParcels, buildoutPolygons, joinOutput, "JOIN_ONE_TO_MANY", "KEEP_COMMON", '', "HAVE_THEIR_CENTER_IN")

 

#create a dictionary to hold list of parcels w/ FID of buildoutPolygon features as key
parcel_dict = {}
with arcpy.da.SearchCursor(joinOutput , ['JOIN_FID','PARCEL']) as cursor:
    for row in cursor:
        parcels = parcel_dict.get(row[0])
        if not parcels:
            parcels = [row[1]]
        else:
            parcels.append(row[1])
        parcel_dict.update({row[0]:parcels})

 
print (parcel_dict)
#use this dict to update the buildoutPolygons FC (maybe a good idea to make a copy and update that instead of original?)
with arcpy.da.UpdateCursor(buildoutPolygons,['OBJECTID_1','PARCELS']) as cursor:
    for row in cursor:
        row[1] = ','.join(parcel_dict[row[0]])
        cursor.updateRow(row)
        
print ("FLU Spatial Join Finished")
print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

KeyError: 1

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.workspace = r"C:\Temp\Scratchworkspace.gdb.gdb"


buildoutParcels = r"C:\Temp\Scratchworkspace.gdb\buildoutParcels1A"
buildoutPolygons = r"C:\Temp\Scratchworkspace.gdb\buildoutPolygons1A""

joinOutput = r"C:\Temp\Scratchworkspace.gdb\sj"
arcpy.analysis.SpatialJoin( buildoutParcels , buildoutPolygons, joinOutput, "JOIN_ONE_TO_MANY", "KEEP_COMMON", '', "HAVE_THEIR_CENTER_IN")


#create a dictionary to hold list of parcels w/ FID of buildoutPolygon features as key
parcel_dict = {}
with arcpy.da.SearchCursor(joinOutput , ['JOIN_FID','PARCEL']) as cursor:
    for row in cursor:
        parcels = parcel_dict.get(row[0])
        if not parcels:
            parcels = [row[1]]
        else:
            parcels.append(row[1])
        parcel_dict.update({row[0]:parcels})

print(parcel_dict)

#find the length of longest parcel list https://stackoverflow.com/a/21839239/11434833    
max_parcels = max(parcel_dict, key=lambda x: len(parcel_dict))

# figure out how many fields you need @ 10 parcels per field
import math
n_fields = int(math.ceil(max_parcels/10)) 

# Create that new many fields .... 
new_fields_list = [] 
for i in range(0,n_fields):
    new_field_name = "PARCEL_" + str(i)
    arcpy.AddField_management(buildoutPolygons, new_field_name, "TEXT")
    new_fields_list.append(new_field_name)

#use this dict to update the buildoutPolygons FC (maybe a good idea to make a copy and update that instead of original?)
new_fields_list.insert(0,'OBJECTID_1')
print(new_fields_list)
with arcpy.da.UpdateCursor(buildoutPolygons,new_fields_list) as cursor:
    for row in cursor:
     print(row)
     for i in range(1,len(row)):
            row = ','.join(parcel_dict[row[0]][i*10:i*10+10])
            cursor.updateRow(row)

print ("FLU Spatial Join Finished")
print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')
0 Kudos
RandyBurton
MVP Regular Contributor

Thanks for sharing some sample data.  I used nested cursors for a quick test and noticed that several of the buildoutPolygons contained a large number of parcels.  If you concatenated the parcel id numbers, you would end up with a string much longer than the field length of 250 characters allowed with a shapefile.  In addition, some of the polygons appear complex (multipart and non-contiguous) , which might indicate some other issues.  Here is screenshot showing one selected polygon feature that has 66 parcels located in it.

One selected polygon showing it contains 66 parcels.

Here is the test script:

polygons = 'buildoutPolygons1'
parcels = 'buildoutParcels1'

# clear all selected features
arcpy.SelectLayerByAttribute_management(polygons, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")

with arcpy.da.UpdateCursor(polygons, ['SHAPE@', 'OID@', 'PAR_COUNT', 'PARCELS']) as cursor:
    for row in cursor:
        arcpy.management.SelectLayerByLocation(parcels, "HAVE_THEIR_CENTER_IN", row[0], "", "NEW_SELECTION")
        par_count = int(arcpy.GetCount_management(pars)[0]) # parcel count
        # get list of parcel id numbers
        pins = []
        with arcpy.da.SearchCursor(parcels, ['PARCEL']) as parcelsCursor:
            for parcelRow in parcelsCursor:
                pins.append(parcelRow[0]) # save PIN in pins list
        # print for testing
        print row[1], par_count # OID@ and count
        print ','.join(pins) # parcel ids in polygon
        print
        # update row
        row[2] = par_count
        # row[3] = ','.join(pins) # not updated as some results longer than field width
        cursor.updateRow(row)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The single polygon from the photo, FID = 34, gave the following results:

34 66
R3590700000,R3590701000,R3590801000,R3590900000,R3591800000,R3594801100,R3595100000,R3595500000,R3595500000,R35957010A0,
R3595901000,R3596001000,R3596001100,R3596800000,R3596801000,R3597200000,R3597301000,R3597500000,R3597700000,R3597701000,
R3598101100,R3598200000,R3598500000,R3598901100,R3599600000,R3599900000,R3600101000,R3600101100,R3600500000,R3601200000,
R3601300000,R3601500000,R3601900000,R3602100000,R3602401000,R3602600000,R3602701200,R3602901000,R3603500000,R3603600000,
R3603700000,R3604000000,R3604301000,R3604900000,R3605100000,R3605200000,R3605201000,R3606400000,R3606400000,R3606401000,
R3606401000,R3606500000,R3606500000,R3606600000,R3606800000,R3607600000,R3607800000,R3607900000,R3608000000,R3608100000,
R3608301000,R3609601000,R3609801300,R3610000000,R3610101000,R3610200000

Hope this helps.

0 Kudos