2

I have a shapefile with many (1000s) points grouped by attributes. I need to determine the distance between each point and the point furthest from it that shares the same group attribute.

Is there a tool that does the opposite of Near (proximity toolset) i.e. that would ideally operate like this Near By Group tool?

  • 1
    Welcome to GIS SE! As a new user please take the tour to learn about our focused Q&A format. A question asking how to do something in code (arcpy) should include your code attempt and description of what happens when you try it. Please edit your question to show what you've tried. Have you looked at the Generate Near Table tool? That will give distances - you could then get a Max value for each point to find the furthest. – Midavalo Mar 27 '17 at 3:19
  • 3
    As you have an advanced license to use Near you can access Generate Near Table which will give you the distance from each point to all other points, then use summary statistics to find the maximum distance for the case of each NEAR_FID. – Michael Stimson Mar 27 '17 at 3:24
3

This is a sample I've written quickly to solve your problem. As an example, we will be working with US cities finding furthest cities within every state. As you have ArcGIS Desktop installed, you have the necessary data to run the code.

Note that there will be one row less in the output table because District Columbia has only one city. I've also left some comments to help you understand the workflow. The execution time for the code is something under 1 minute (3149 cities in the input feature class).

import os
import arcpy
from arcpy.da import SearchCursor

arcpy.env.overwriteOutput = True

cities = r'C:\Program Files (x86)\ArcGIS\Desktop10.4\TemplateData\TemplateData.gdb\USA\cities'
group_attr = 'STATE_NAME'
scratch_gdb = r'in_memory' #r'C:\GIS\Temp\ArcGISHomeFolder\empty.gdb'

grouping_vals = list(set(f[0] for f in SearchCursor(cities, group_attr))) #'OBJECTID < 20'
lookup = {}

for val in grouping_vals:
    print val
    #create a feature layer keeping only cities with a specific state
    feat_lyr_name = 'cities_lyr_' + val.replace(' ','')
    arcpy.MakeFeatureLayer_management(in_features=cities,
                                      out_layer=feat_lyr_name,
                                      where_clause=''' {0} = '{1}' '''.format(group_attr,val))

    #count number of cities in the state
    group_feature_count = int(arcpy.GetCount_management(in_rows=feat_lyr_name).getOutput(0))

    #generate near table for every city in the state (all-to-all)
    near_table = os.path.join(scratch_gdb,'near_{}'.format(val.replace(' ','')))
    arcpy.GenerateNearTable_analysis(in_features=feat_lyr_name, near_features=feat_lyr_name,
                                    out_table=near_table,
                                    closest='ALL')

    #compose a dictionary {source_fid: destination_fid} for only top rank (interested only in furthest)
    group_lookup = {f[0]:f[1] for f in SearchCursor(near_table, ['IN_FID','NEAR_FID','NEAR_RANK'],
                                                    where_clause='NEAR_RANK = {}'.format(group_feature_count-1),
                                                    sql_clause=(None, 'ORDER BY NEAR_RANK DESC'))}

    lookup.update(group_lookup)

#inserting new rows into a gdb table
with arcpy.da.InsertCursor(r'C:\GIS\Temp\ArcGISHomeFolder\Default.gdb\DistancesLookup',
                           ['SourceFID', 'DestinationFID']) as cur:
    for k, v in lookup.iteritems():
        cur.insertRow((k, v))
3

The workflow below is nearly identical to 1st answer, but uses no scripting:

# add coordinates to points to fascilitate distance calculations later on
arcpy.AddGeometryAttributes_management("points","POINT_X_Y_Z_M")

arcpy.SpatialJoin_analysis("points", "points","../points_SpatialJoin", "JOIN_ONE_TO_MANY", "INTERSECT", search_radius="1000000 Meters")
# select and delete non-matching pairs
arcpy.SelectLayerByAttribute_management("points_SpatialJoin", "CID <> CID_1")
arcpy.DeleteFeatures_management("points_SpatialJoin")
# add distance field and populate it
arcpy.AddField_management("points_SpatialJoin", "DISTANCE")
math.hypot( !POINT_X!- !POINT_X_1!, !POINT_Y!- !POINT_Y_1!)
# sort descending and delete identical 
arcpy.Sort_management("points_SpatialJoin", "../sorted", "DISTANCE DESCENDING")
arcpy.DeleteIdentical_management("sorted", fields="TARGET_FID")

Table of "sorted" has enough info to obtain this:

enter image description here

-1 BTW for ignoring wealth of available ArcGIS tools and asking for out of the box solution.

  • Good one! How well will your solution scale with large number of points? I've run the Spatial Join on a point feature class with ~3K points. Got back a point fc with ~6.3 mln points (with shapes) and it took ~5min to run on a powerful workstation. I think it's a bit unnecessary to keep the shapes, quite an expensive operation. Also, working with such large tables won't be efficient in ArcGIS. Your code would run fine for some hundreds points, but it won't scale. – Alex Tereshenkov Mar 28 '17 at 7:21

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.