1

My goal is to create a layer of lines representing the closest street segment to a set of points.

The code:

arcpy.SpatialJoin_analysis(
    target_features=point_req,
    join_features=selected_streets,
    out_feature_class=pt_st_join_output,
    join_operation='JOIN_ONE_TO_ONE',
    join_type='KEEP_COMMON',
    match_option='CLOSEST',
    distance_field_name='CLOSEST')

Works almost perfectly, doing the join correctly but the geometry included in the table is from the target layer, points, rather than the join layer, lines.

I could use a cursor to run through the points layer and build a layer of lines by finding each row's joined ID in the lines layer. I'm hoping to avoid this out of concerns about runtime since I'd have to loop through the lines layer for each point.

It seems like there should be a more elegant way to do this.

2
  • yeah I tried before posting, the problem I ran into was that I'm trying to create a subset of the streets. With 100 points and 1000 streets, my code returns 100 lines, when i flipped them, the geoms were lines but there were 1000 rows, one for each street. I ~could~ then filter to get only the lowest distance for each Unique point ID. That's fairly crude too as I'd have to loop through creating a dict of some sort and then make a new layer based on the dict. edit: this was in response to a suggestion to reverse the join that was then deleted. Dec 1 '20 at 13:35
  • Dont you get the OID of the closest line in the output? Copy the results to a table with no geometries, join this table back to the lines. Or list the OIDs using a cursor, select by list and export as a new feature class
    – BERA
    Dec 1 '20 at 15:39
0

If you could use Select by Attribute on the line layer with a query along the lines of "select line where streetID = point_closest_street_ID", then that selection could be exported to its own feature class if needed.

1
  • potentially, a couple challenges to that are: 1 there are going to be some lines with multiple points on them, so I'd need to include those lines multiple times. 2 i would need to join the point attribute data to the selected line output data 3 I'm not sure there's a way to use the attribute values of one table to select rows on another table. Dec 1 '20 at 13:46
0

What I ended up doing was creating a new feature class with an insert cursor on that, creating a search cursor on the join output that contained the line OID, creating a search cursor on the lines table and looping through to build the whole thing manually.

        pts_cols = ['RequestID','Description','JOIN_FID','CLOSEST','unique_id']
        sts_cols = ['OBJECTID','SHAPE@','FULLNAME','strt_type', 'unique_id']
        ins_cols = ['RequestID','Description','pt_st_dist','fullname','strt_type','SHAPE@']

        with arcpy.da.InsertCursor(final_output, ins_cols) as ins_curs:     
            with arcpy.da.SearchCursor(in_table=actual_merge_output, field_names=pts_cols) as ptscursor:
                for ptsrow in ptscursor:
                    arcpy.AddMessage('working on ')
                    arcpy.AddMessage(ptsrow[0])
                    with arcpy.da.SearchCursor(all_streets, sts_cols) as stscursor:
                        for stsrow in stscursor:
                            if ptsrow[4] == stsrow[4]:
                                arcpy.AddMessage('found a match')
                                arcpy.AddMessage(stsrow[2])
                                ins_curs.insertRow((ptsrow[0],ptsrow[1],ptsrow[3],stsrow[2],stsrow[3],stsrow[1])) 

It's pretty ugly in my opinion but it allows for multiple matches and combines attributes from the source and the join tables,

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.