I'm trying to generalize the attributes of a set of polygons(let's say they're census blocks with a population property) into another, overlapping set of polygons(let's say it's just a grid with no properties)

I'm certain there's a word for this problem that I've never heard of and never thought to search... If that's so, please just point me in the right direction!

I want to make a choropleth map that shows the population density of the area without showing the shape of the census blocks themselves. I want to put their attributes into the regular grid. BUT, there's of course a lot of overlap, and irregular shapes don't fit neatly within a square.

I need something that can:

  1. Assume that population is evenly distributed across the census block polygons.
  2. for each square in the grid, calculate..
    1. what polygons are even a little bit under it, and for each one, what portion of that irregular polygon is indeed under it.
    2. Then, lets say we have an irregular census block polygon that has a population of 100, and is 37% covered by the grid-block of interest... It would need to calculate the amount of the population attribute to assign to the block, in this case, exactly 37, assign it to that block, and then do the same, adding for every other shape under that block before moving on.
  3. Then do that for all the other polygons in the grid layer.

I should end up with the exact same total population, just abstracted and generalized into regular shapes.

How can I do this, particularly in QGIS?

I really just want to count up some point data (points in polygon) and create a choropleth corrected for population density.

  • 1
    It is certainly possible to solve the problem with vector data. But this will require many steps. Hence my question: have you ever tried to solve the problem via a density analysis? Convert your polygons to centroids (points). Create a raster density map from this points. – Jens Nov 29 '12 at 13:04

It can be done but it isn't pretty! One possible solution could be as follows:

  1. Add an 'Area' field to your Census data if it doesn't already exist (call it 'OriginalArea')
  2. Union your grid data with the Census data.
  3. Calculate a new field based on the polygon actual area divided by OriginalArea and multiplied by Population
  4. Do a spatial join with the grid data as your target and the data from the previous step as the join vector and select the option to "Take summary of Intersecting Features" and set it to 'Sum'

This will work in theory BUT there is a 'gotcha'. Because QGIS just does a basic intersect it will also gather up the data from polygons that touch the edge of the grid squares but are not contained within it. This is a problem you need to overcome. You can do it a couple of ways:

  1. Writing an SQL or Python function to iterate over your grid at step 4, selecting your data from step 3 from based on the matching grid id (which should be present from your intersection at step 2)
  2. Buffer your grid by a negative amount to make the cells smaller by a small amount. Then perform the spatial join as per step four and finally do a simple join to get the attributes from your de-buffered grid back into the original grid.

If you want to do it using vector-based analysis, you can accomplish this using PostGIS (and maybe SpatiaLite as well), using SQL.

Say we have two spatial tables, blocks and grids, with population fields in both of them. You need to calculate the population field for grids using something like this:

UPDATE grids AS g
SET population = (
  SELECT SUM( ST_Area( ST_Intersection(g.geom, b.geom) ) / ST_Area(b.geom) * b.population )
    FROM blocks AS b
   WHERE ST_Intersects(g.geom, b.geom)

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.