1

I am trying to compare the 2000 Census county boundaries with the 2010 Census county boundaries. Each county is uniquely identified in a given year by a FIPS code and I want to compare if the polygon represented by given FIPS code z in 2000 is different from the polygon represented by the same code (z) in 2010. By different I mean any change to the geometry, regardless of whether it modifies the area of the polygon.

My ideal output is a table/spreadsheet with two columns - one containing the 2000 Census FIPs codes and the other indicating some way of identifying if a that code references different geometries/polygons in the two years. This indicator could be a boole (TRUE/FALSE), a binary indicator (1/0), some continuous variable, or any other indicator.

I am looking for a solution in either R or QGIS.

Notes:

  • Why not overlay 2000 with 2010 and see where FIPS codes are different? You may need to do some cleaning/eliminating of sliver polygons. – Michael Stimson Jul 13 '16 at 2:44
  • (1) How? (2) In anticipation: shouldn't there not be sliver polygons in Census shape files? – question Jul 13 '16 at 4:03
  • (1) gis.stackexchange.com/questions/25061/… and gis.stackexchange.com/questions/42721/… (2) you wish jellyfish! In my experience even data prepared as pedantically as census data does not 100% coalesce where expected. Have a read of gis.stackexchange.com/questions/11004/… – Michael Stimson Jul 13 '16 at 5:05
  • 1
    (1) How equal is equal? Do you want all coordinates to be the same right down to the floating point precision? (2) Have you looked at the coordinates of a few polygons to see if the coords are equal at that precision for 2 regions you know are unchanged? – Spacedman Jul 13 '16 at 7:14
2

Load your shapefiles into R as SpatialPolygonsDataFrame objects - lets call them p1 for the year 2000 and p2 for the year 2010. Drop any rows in p1 with fips codes that aren't in p2 - these would be county fips codes that don't exist any more, so their geometry has changed.

Also, drop any rows in p2 that don't have a fips code in p1. These are new fips codes with no partner from 2000.

Order your objects so that you now have two spatial data frames with the same number of rows with matching fips codes. You should have:

all(p1$fips == p2$fips)

return TRUE. This makes it easier to match across the two objects - p1[i,] should be tested against p2[i,].

So far, just basic R data frame handling which I won't go into. Matching and subsetting of data frames, basic stuff.

Now you can use rgeos to test the difference between each polygon with a simple sapply call:

> require(rgeos)
> sapply(1:nrow(p1),function(i){is.null(gDifference(p1[i,],p2[i,]))})
 [1]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
[25]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[37]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[49]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE

And there's my boolean vector of changes. gDifference returns null if the geometries are the same.

Save the result to play with it:

> changed = !sapply(1:nrow(p1),function(i){is.null(gDifference(p1[i,],p2[i,]))})
> which(changed)
[1]  5 23 54

You can then do something like:

> plot(p1[5,],border="grey",lwd=10)
> plot(p2[5,],add=TRUE)

to plot both versions of changed polygons to see what might be going on.

If there are changes in the data precision that aren't the sort of changes you are looking for then you might need to do something a bit craftier like compare one boundary against a buffered version of the other boundary, with the buffer size set to catch the imprecision but no lose any genuine boundary changes.

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.