Eye candy is the best way to get your poster noticed at a conference and choropleth maps are some of the tastiest morsels. Here’s a quick tutorial on how to make one in R. It’s not a beginner topic, so bear with it. The approach below probably requires the least overheard in terms of new libraries or plotting paradigms, but it is also probably the least powerful method.
- Install the maps library. The command
install.packages("maps")usually does the trick, although I’m not too familiar with non-linux environments.
- Load the necessary libraries and data objects. The last line loads the state names and some data to play with.
- Make a basic map, just to see how it looks.
map("state", fill=FALSE, boundary=TRUE, col="red")
- Now come the hard parts. Presumably you want to color each state according to some numerical variable. I’m going to use land area, which is called state.area (loaded in step 2). The problem is that the
mapcommand actually draws 63 regions that comprise the continental US, while our data vector has one entry for each of the 50 states.
- To get the 63 regions, make an invisible map.
mapnames <- map("state", plot=FALSE)$names
- Note that each region’s name is either a state or a state followed by a colon and then an island. We’ll use the colon to isolate the state names.
region_list <- strsplit(mapnames, ":")
mapnames2 <- sapply(region_list, "[", 1)
- Now we need to match our data to the state names as they appear in the map.
m <- match(mapnames2, tolower(state.name))
map.area <- state.area[m]
Now each of the 63 regions is associated with the land area corresponding to its state (except poor Washington, DC, which is missing from the original state.area variable).
- The next step is to define the colors for our map. Of the basic R palettes, I think the
heat.colors()look best. I use 8 colors; use a higher number if you want more subtle distinctions. I also reverse the color vector so that higher land area states show up redder.
clr <- rev(heat.colors(8))
- Now we need to collapse our map areas into bins, one per color.
area.buckets <- cut(map.area, breaks=8)
- And finally, for all the glory…
map("state", fill=TRUE, col=clr[area.buckets])