Dot Density Maps in R

Sparked by Bill Rankin's alternative approach to map segregation in Chicago, dot density maps of segregation in US cities have become popular (here and here).

I was interested in creating them as well, so here is my R code, which should be easy enough to adapt. I used the USCensus2000 package with block level data, both conveniently available as R library. My example below for Charleston, SC took a while on my MacBook Pro, so depending on your CPU running this for larger cities may require a bit of patience.

It is important to acknowledge the limitations of this kind of visualization and you are also cautioned on the help page of dotsInPolys, the core function from the maptools R package which does all the heavy lifting in this case: "Waller and Gotway (2004) Applied Spatial Statistics for Public Health Data (Wiley, Hoboken, NJ) explicitly warn that care is needed in plotting and interpreting dot density maps (pp. 81-83)".

R:
  1. install.packages("UScensus2000", dependencies=T)
  2. library(UScensus2000)
  3. install.blk("osx") #install block level data (> 2 GB, so be patient.)
  4.  
  5. # Ignored Warning message below but all worked ok:
  6. #    In download.file(url, destfile, method, mode = "wb", ...) :
  7. #      downloaded length -1817522093 != reported length 2147483647
  8. library(UScensus2000blk)
  9.  
  10. # ignore license restiction on gpclib
  11. gpclibPermit()
  12.  
  13. chas<-poly.clipper(name="Charleston",state="SC",level="blk")
  14. mp<-poly.clipper(name="Mount Pleasant",state="SC",level="blk")
  15. nchas<-poly.clipper(name="North Charleston",state="SC",level="blk")
  16.  
  17. # conveniently, this that creates a SpatialPolygonsDataframe:
  18. summary(chas)
  19.  
  20. # merge those three regions
  21. chasregion <- spRbind(chas,nchas) #spRbind takes only two parameters at a time
  22. chasregion <- spRbind(chasregion,mp)
  23.  
  24. # create the density dots as SpatialPointsDataframe for different ethnicities
  25. # depending on size of population can take a while...
  26. dots.b <- dotsInPolys(chasregion, as.integer(chasregion$black/20))
  27. dots.b$ethnicity <-"black"
  28. dots.w <- dotsInPolys(chasregion, as.integer(chasregion$white/20))
  29. dots.w$ethnicity <-"white"
  30. dots.a <- dotsInPolys(chasregion, as.integer(chasregion$asian/20))
  31. dots.a$ethnicity <-"asian"
  32. dots.h <- dotsInPolys(chasregion, as.integer(chasregion$hispanic/20))
  33. dots.h$ethnicity <-"hispanic"
  34. dots.o <- dotsInPolys(chasregion, as.integer(chasregion$other/20))
  35. dots.o$ethnicity <-"other"
  36.  
  37. # combine with spRbind
  38. dots.all <- spRbind(dots.b, dots.w)
  39. dots.all <- spRbind(dots.all, dots.a)
  40. dots.all <- spRbind(dots.all, dots.h)
  41. dots.all <- spRbind(dots.all, dots.o)
  42.  
  43. # plot with ggplot
  44. library(ggplot2)
  45. gpclibPermit()
  46.  
  47. # extract the dataframe for ggplot
  48. ethno.df <- data.frame(coordinates(dots.all)[,1:2], ethnicity=dots.all$ethnicity)
  49.  
  50. #make the basemap
  51. bmap <- ggplot(chasregion, aes(x = long, y = lat)) + geom_polygon(aes(group = group), colour = I("grey65"), size=0.2, fill = "white") + coord_equal()
  52.  
  53. #add dots
  54. map <- bmap + geom_point(data=ethno.df, aes(x=x,y=y, colour = factor(ethnicity)), size=0.8) + scale_colour_manual (values=c("light green", "cyan", "orange", "grey", "magenta"))  + opts(panel.grid.major=theme_blank(),panel.grid.minor=theme_blank(), title="Ethnic breakdown of population in and around Charleston, SC in 2000, each dot=20")
  55.  
  56. # save as PNG
  57. ggsave(plot=map,filename="ddMap.png", width=18,height=10)

Here is the result:

No TweetBacks yet. (Be the first to Tweet this post)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>