Randomly assign points to new location based on polygon id - ArcGIS Pro

751
4
02-13-2023 12:32 PM
Labels (3)
PrinceAmegbor
New Contributor

I have multiple-point data and polygon data. All the points in the point data layers are supposed to lie within the polygon. However, some of the points are clustered at one XY position (about 10% of all the point data), for the purpose of this question LAT=0 and LONG=0. However, the attribute data for the points contain a field at indicates which region in the polygon the point can be found.

I would like to move the clustered points to a random XY location in their corresponding region (based on the geographic information from the polygon data). Does anyone have an idea of how to do this efficiently in ArcGIS Pro?

 

The attached figure shows the points and the polygon. The point in the gulf is the location of all the points that needs to be moved.

0 Kudos
4 Replies
DavidPike
MVP Frequent Contributor

Are you comfortable using Python/cursors?

Either way, the first step I can see is generating those random points.  It would be more efficient and robust to generate only those you need, so I would summarize the table of 0,0 values and create a dictionary, key=region value=number of occurences

then iterate over your region polygons to generate x number of random points in each, with x being the value of the dictionary region key.

when this is done, spatial join those points to append the region attribute to them.

then it comes down to running a cursor on all the points, with another loop  of the 0,0 points - running a match against the same region attribute, when this happens you transfer the random point geometry token to the 0,0 point.  You'll need some if logic like if @shapexy != (0,0) that ((NB that syntax is going to be wrong!)) to ensure the same point isn't picked again after the new xy is transferred of course.

0 Kudos
PrinceAmegbor
New Contributor

Thank you, David. I am not conversant with python but I can do it. Is there a simple code or script for implementing your recommendation in python?

0 Kudos
JohannesLindner
MVP Frequent Contributor

Similarly to @DavidPike 's answer, I would summarize the points by their polygon attribute and generate random point for each region your problematic points belong to. But I would skip the spatial join and just update the geometry directly.

Steps to use:

  1. Backup your data! This will change the geometry of the problematic points. Create a backup.
  2. Select the problematic points
    • this will remove the need for the geometry logic David suggested
  3. Copy paste the script into the ArcGIS Pro Python window
  4. Edit the varibales point_layer, polygon_layer, polygon_id, and point_polygon_id
  5. Run the script

 

# names of the point and polygon layers in the current map
point_layer = "TestPoints"
polygon_layer = "TestPolygons"

# names of the relationship fields
polygon_id = "TextField"        # primary key of the polygon layer
point_polygon_id = "TextField"  # foreign key that links the points to the polygons

# get the regions where the points should be
point_regions = [row[0] for row in arcpy.da.SearchCursor(point_layer, [point_polygon_id])]
regions = {pr for pr in point_regions}

# loop over the regions
for region in regions:
    # get the count of points that belong in that region
    point_count = len([pr for pr in point_regions if pr == region])
    # select the region polygon
    query = f"{polygon_id} = '{region}'"  # my id fields are text fields. if yours are not, remove the single quotes around {region}
    arcpy.management.SelectLayerByAttribute(polygon_layer, "NEW_SELECTION", query)
    # generate random points in that region and extract their geometries
    random_points = arcpy.management.CreateRandomPoints("memory", "RandomPoints", polygon_layer, None, point_count)
    new_shapes = [row[0] for row in arcpy.da.SearchCursor(random_points, ["SHAPE@"])]
    # start updating the points that belong in this region
    query = f"{point_polygon_id} = '{region}'" # again, remove the single quotes if you're working with numbers
    with arcpy.da.UpdateCursor(point_layer, ["SHAPE@"], query) as u_cursor:
        # loop over the points
        for i, row in enumerate(u_cursor):
            # copy the new geometries
            u_cursor.updateRow([new_shapes[i]])

 

 

Before:

JohannesLindner_0-1676367491645.png

 

After:

JohannesLindner_1-1676368892094.png

 

 


Have a great day!
Johannes
PrinceAmegbor
New Contributor

Thank you Johannes. 

0 Kudos