I am trying to create a shapefile of equal population size buffer rings. Similar to the procedure of creating multi-ring buffers of distance around a point, find the intersects of the buffers with a polygonal layer, and then dissolve with the required statistics (e.g. https://support.esri.com/en/technical-article/000010582).

I have a point layer (Atlanta) and a polygon layer (Atlanta metropolitan area census block groups). I want to create a new polygon layer of equal population size (say 5% of total population) rings around the point layer, using population attribute from the census block groups. So a total of 20 rings around the city, each equal of 5% of population. Distance and area of each ring obviously differs.

So far I have tried to use ArcMap Grouping Analysis and modifying the process in the link above.

Any suggestions on how to implement this?

I can use Python for this if needed.

I expect to have an output similar to this:

this is Service Area Analysis output from ArcMap

  • 1
    Population equality is significantly more complex than travel time, each census tract has a set population, including it adds that value to the cluster but there will be a point where the population accumulation is exceeded which then onflows to the next and next.. until the last band has way less than 5%. Finding the seed location is also a challenge, do you take town hall, geographic centre or mean feature? You could start from the outside and work in, iterating an inside buffer which will lead to a central point that may not be what you'd pick... not a trivial task by any means! Commented Oct 7, 2020 at 7:51
  • Thanks for your quick reply @MichaelStimson. Indeed not a trivial task, though I was sure someone did it before me. Just for clarification, city centre will be city hall. From there I want to create buffers of block groups with equal population (5% of total pop). I was thinking on creating multi-ring buffer of DISTANCE every 500m. Then, using intersect and dissolve, calculate the population in each ring, and then aggregate adjacent rings hold 5% of population (or as close to it). The cons of this methods that it required strong computational capabilities, which I don't have access to. Thanks.
    – ALCZ
    Commented Oct 7, 2020 at 9:04
  • If you're going to do it that way you need to express the population as an area, population per square unit (ppsu) then intersect/union multiple ring buffer (~25m should be suitable), calculating the intersecting area and then expanding ppsu * area to estimate the population of the fragment then dissolve the rings using estimated population as a statistic field then interactively select the dissolved rings from the centre in an edit session and dissolve as soon as you get within tolerance of the 5% threshold. It will require some processing power but should process over a weekend. Commented Oct 8, 2020 at 0:08
  • Yes, exactly what I had in mind, though I hoped someone will come up with a better (faster) solution.
    – ALCZ
    Commented Oct 8, 2020 at 5:15

1 Answer 1


Reasonably accurate results can be achieved without much iterations. Create 100 travel polygons with same small step to cover entire area. I did it via computing travel raster:

enter image description here

and raster calculator Int(travel/1499.816772)

Assuming that population spreads evenly over Census meshblock area:

enter image description here

Intersect it with travel polygons and summarize population in intersection bits pro-rata their area vs meshblock area. Accumulate population in travel belts into new column and convert to percentage of total:

enter image description here enter image description here

Next step is to find intersection points on the TravelDistance(Percentage) curve for given break points, e.g. 5,10,15...100:

enter image description here

and draw relevant contours on travel distance raster:

enter image description here

I used following script to derive contour values, although they can be computed using paper and pen from values in travel belts table:

import arcpy
import numpy as np
tbl = arcpy.da.TableToNumPyArray("BELTS",("PERCENT","TRAVEL"))
breaks = np.linspace(10, 100, 10)
contourList =[]
for breakValue in breaks:
arcpy.gp.ContourList_sa(arcpy.Raster("TRAVEL"), "C:/SCRATCH/Contours", contourList)
  • That is an awesome metric, combining main roads network and population for a visually appealing result, more interesting than concentric circles radiating out from a centre point. Hopefully this meets the OP's needs and they don't need concentric circles for some sort of modelling. +1 from me and I'll tuck this away into my box of tricks, I'll whip it out when needed and look like a genius. Commented Oct 8, 2020 at 7:20
  • Wow, thanks a lot @FelixIP, it looks great and much simple than what I intended to do. I got it all right, except your first fig. Could you please elaborate on how you created the travel raster?
    – ALCZ
    Commented Oct 8, 2020 at 8:10
  • Are you dealing with travel distance of straight crow fly?
    – FelixIP
    Commented Oct 8, 2020 at 8:50
  • Hi, yes I am. road network is not required.
    – ALCZ
    Commented Oct 8, 2020 at 8:56
  • Use euclidean distance to point.
    – FelixIP
    Commented Oct 8, 2020 at 8:58

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.