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]
install.packages("UScensus2000", dependencies=T)
library(UScensus2000)
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
library(UScensus2000blk)
# ignore license restiction on gpclib
gpclibPermit()
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: