I have what seems like a trivial problem, but I can't come up with a solution.

So I have two spatial tables (points) -

  1. Buildings ~1000 records (addresses; with a common field identifying the builder)
  2. Builders ~100 records (addresses, can be linked (join or relate) to 1st table based on builder ID).

My goal is to select all the buildings that are outside of 1 km zone (buffer) from their builder.

Is there a tool-based solution to that? I'm sure that it can be done using python, but I'm not familiar enough to come up with the code. I'm using ArcGIS Desktop 10.3.

  • Some additional context: There is no specific requirements for using buffers and using the 1 km range. The goal is to identify anomalies in the data (i.e. builder has a number of projects in the same city, but randomly also has a project in a 100 kms away from their home address). So ideally I want to be able to set the color/size of the buildings depending on their proximity to builder (i.e. red dots for all buildings outside of 100 km range, yellow for 10 km etc.).
    – Ruslan
    Commented Oct 25, 2017 at 22:58
  • Intersect points with buffers. Every point with different IDs is your red dot.
    – FelixIP
    Commented Oct 26, 2017 at 1:56

2 Answers 2


I can think of a non-python solution that would involve a few processing steps:

  1. Create a 1 km buffer of the buildings.

  2. Do a spatial join of the builder layer to the building buffer. This should give you an output that provides all builder IDs located within the 1 km buffer of each building.

  3. Identify and flag instances where the associated builder ID matches with the output from the spatial join. If the data is correct, this should result in only 1, or no, matches, for each building. For this example, let's call this field, "Builder_Match"

  4. Dissolve on building name or ID and summarize (addition) on "Builder_Match." Any building with a sum of 0 should have a builder that is outside the 1km zone.

For additional buffer ranges, you can use the buffer wizard to create those buffer rings and run the same analysis.

  • Unfortunantely, this approach would not really work, as buildings and builders have huge overlaps, i.e. one geog. point can have points for 10 builders. With the realistic buffer size I'm using (10-100km), it ends up being a collection of overlapping buffers, that have 10's of builder points within them, so I'm not really sure how you can get through step 3..
    – Ruslan
    Commented Oct 27, 2017 at 21:45
  • Isn't there only a one-to-one relationship of building to builder? Assuming that is the case, you would do a spatial join, create a new field, and identify the rows in which the building's designated builder matches the builder from the intersection. So even if you end up with 20 builders that are within 10 km of your building, there's only one builder that actually matters.
    – saoirse
    Commented Oct 27, 2017 at 23:33
  • There is one-to-one (actually many-to-one) tabular relationship between buildings and builders. As I said there are huge spatial overlaps of buffers. For instance: there are 15 buildings within 100 meters, each has a 10km buffer, within these (almost completely overlapping) buffers, there are 3 builders that are all referenced to same point. Which one of them would be "assigned" to each building? Only first Builder will be assigned. How do you get through steps 3 to 4, considering that most building would have identical and wrong result of being assigned the first overlapping builder?
    – Ruslan
    Commented Oct 29, 2017 at 20:43
  • Maybe you can upload some data so I can understand the situation better? What I have in mind is an intersect (or spatial join) of the building buffers with your builders. Overlaps shouldn't matter. In your above example, let's say 3 builders intersect the buffer of only 2 of these 15 buildings (and the matching builder is present for both). Your intersect should then result in 6 records.
    – saoirse
    Commented Oct 30, 2017 at 16:26
  • You would do an attribute query to match the correct builder (from the buildings table) with the builder's ID. Flag these as "1." Then run a dissolve on that field. Your results tell you that 13 of 15 buildings do not have a matching builder within 10km, while 2 do. But again, I could be interpreting your situation incorrectly.
    – saoirse
    Commented Oct 30, 2017 at 16:26

This should be manageable - if you load both point feature classes into ArcMap, you can enter the following code into the Geoprocessing -> Python window to populate a list of unique Builder IDs, then iterate through the Building features and select features that are more than 1000 meters from the corresponding point for that building ID. Note, the layer names must match, "Builder" and "Buildings", the units for search distance will match the Coordinate Reference System for the data frame (UTM zone would be good here, so you could leave it at 1000 for meters in search distance), and you should change the field name for builder ID to match whatever is in these tables. After running this, you should have a selection on the Buildings class that you can then either export into its own feature class, or else modify to symbolize as outside of their buffer area.

builder_id = []
cursor = arcpy.SearchCursor("Builder")
for row in cursor:
    id = row.getValue("[Builder ID attribute field name]")
del cursor

cursor = arcpy.SearchCursor("Building")
for row in cursor:
    for id in builder_id:
        lyr = arcpy.mapping.Layer("Builder")
        lyr.definitionQuery = "[BUILDER ID attribute field name] = '" + id + "'"
        if row.getValue("[Builder ID attribute field name]") == id:
            arcpy.SelectLayerByLocation_management("Building", "Intersect", lyr, 1000, "ADD_TO_SELECTION", "INVERT")
        del lyr
del cursor
  • I have tried using this code. One modification required was converting the Builder_ID column to text, or else it would throw an error for line 12: TypeError: cannot concatenate 'str' and 'int' objects. However, even after working with a string it seems to produce some wrong output. 1. It deletes all builder records except the last one it iterated through (last record in the Builder table). 2. Output just has all the buildings selected (even the ones that are within 1 km buffer area of that last record). I did check all the external parts (projection: UTM; names etc.).
    – Ruslan
    Commented Oct 27, 2017 at 20:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.