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)".

install.packages("UScensus2000", dependencies=T)
install.blk("osx") #install block level data (> 2 GB, so be patient.)
# Ignored Warning message below but all worked ok:
#    In download.file(url, destfile, method, mode = "wb", ...) :
#      downloaded length -1817522093 != reported length 2147483647
# ignore license restiction on gpclib
chas<-poly.clipper(name="Charleston",state="SC",level="blk") mp<-poly.clipper(name="Mount Pleasant",state="SC",level="blk") nchas<-poly.clipper(name="North Charleston",state="SC",level="blk")   # conveniently, this that creates a SpatialPolygonsDataframe: summary(chas)   # merge those three regions chasregion <- spRbind(chas,nchas) #spRbind takes only two parameters at a time chasregion <- spRbind(chasregion,mp)   # create the density dots as SpatialPointsDataframe for different ethnicities # depending on size of population can take a while... dots.b <- dotsInPolys(chasregion, as.integer(chasregion$black/20)) dots.b$ethnicity <-"black" dots.w <- dotsInPolys(chasregion, as.integer(chasregion$white/20)) dots.w$ethnicity <-"white" dots.a <- dotsInPolys(chasregion, as.integer(chasregion$asian/20)) dots.a$ethnicity <-"asian" dots.h <- dotsInPolys(chasregion, as.integer(chasregion$hispanic/20)) dots.h$ethnicity <-"hispanic" dots.o <- dotsInPolys(chasregion, as.integer(chasregion$other/20)) dots.o$ethnicity <-"other"   # combine with spRbind dots.all <- spRbind(dots.b, dots.w) dots.all <- spRbind(dots.all, dots.a) dots.all <- spRbind(dots.all, dots.h) dots.all <- spRbind(dots.all, dots.o)   # plot with ggplot library(ggplot2) gpclibPermit()   # extract the dataframe for ggplot ethno.df <- data.frame(coordinates(dots.all)[,1:2], ethnicity=dots.all$ethnicity)   #make the basemap bmap <- ggplot(chasregion, aes(x = long, y = lat)) + geom_polygon(aes(group = group), colour = I("grey65"), size=0.2, fill = "white") + coord_equal()   #add dots 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")   # save as PNG ggsave(plot=map,filename="ddMap.png", width=18,height=10) [/r] Here is the result:

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