Bivariate choropleth maps

Kevin Wright


R setup

knitr::opts_chunk$set(fig.align="center", fig.width=6, fig.height=6)

Single-variate choropleth maps

The two maps below show male and female cancer rates on separate maps. The rates are coarsely binned into three classes so as to be somewhat comparable to the bivariate choropleth below.

require(latticeExtra) # USCancerRates, mapplot
require(maps) # map
require(classInt) # classIntervals, findCols
require(grid) # viewport, pushViewport
require(pals) # brewer.blues, stevens.pinkgreen

  mapplot(rownames(USCancerRates) ~ log(rate.male) + log(rate.female),
          data = USCancerRates,
          colramp = brewer.blues,
          map = map("county", plot = FALSE, fill = TRUE,
                    projection = "tetra"),
          breaks=classIntervals(log(USCancerRates$rate.female), n=3, style='quantile')$brks,
          scales = list(draw = FALSE))

Comments on the single-variate choropleth maps

  1. It is fairly easy to choose a color scheme (e.g. BrewerPal sequential colors).

  2. It is fairly easy to interpret a single-variate map.

  3. If two single-variate maps are drawn with a common scale for the variates (as shown here), the breakpoints for the colors might be suitable for one variate and less suited for the other variable. For example, the rates for females are high in West Virginia and the lower Mississippi River valley, but the breakpoints on the color scale do not allow for identification of similar features for males.

Bivariate color classes

Each variate is divided into thirds (based on percentiles) and a joint classification for all 9 combinations is defined.

cols <- stevens.pinkgreen; nbins <- 3

# categorize rates into 3 percentile bins
brksm <- classIntervals(log(USCancerRates$rate.male), n=nbins, style='quantile')
## Warning in classIntervals(log(USCancerRates$rate.male), n = nbins, style = "quantile"):
## var has missing values, omitted in finding classes
brksf <- classIntervals(log(USCancerRates$rate.female), n=nbins, style='quantile')
## Warning in classIntervals(log(USCancerRates$rate.female), n = nbins, style = "quantile"):
## var has missing values, omitted in finding classes
classm <- findCols(brksm)
classf <- findCols(brksf)
# convert x,y classes into a joint class x+3(y-1)
USCancerRates$class2 <- classm + nbins*(classf-1)

# scatterplot of two variates showing bins
plot(log(rate.female) ~ log(rate.male), data=USCancerRates,
     col=cols()[USCancerRates$class2], pch=19,
     xlim=c(4.5, 6.5), ylim=c(4.0, 6))

Bivariate choropleth maps

m3 <- mapplot(rownames(USCancerRates) ~ class2, data = USCancerRates,
              colramp=cols, breaks=seq(from=0.5, by=1, length=nbins*nbins+1),
              map = map("county", plot = FALSE, fill = TRUE,
                        projection = "tetra"),
              scales = list(draw = FALSE))
suppressWarnings(print( m3 ))
# add the color legend
m3leg <- levelplot(matrix(1:(nbins*nbins), nrow=nbins), axes=FALSE, col.regions=cols(),
                   xlab="male  -->", ylab="female  -->", cuts=8, colorkey=FALSE,
vp <- viewport(x=.15, y=.25, width=.2, height=.2)
print(m3leg, newpage=FALSE)

# test
print(m3, more=TRUE)
## Warning in (function (x, y, map, breaks, colramp, exact = FALSE, lwd = 0.5, : 65
## unmatched regions: alaska,nome, alaska,wade hampton, alaska,haines, alaska,....
print(m3leg, position=c(.05, .15, .25, .35), more=FALSE)

Comments on the bivariate choropleth map

  1. Choosing a good color scheme requires some care. See Stevens (2015).

  2. The single map is larger (than two single-variate choropleth maps), which makes it easier to see individual counties.

  3. The larger map also reduces the relative amount of black ink to draw the county boundaries.

  4. Because there are few bins for each variate, within-bin structure for individual variates could be overlooked.

In the example above, the rates of cancer are high for both men and women in West Virginia and the lower Mississippi River valley. South and east of that area, the counties are more green than blue, indicating a higher rate for men than for women.


Stevens, Josh. 2015. “Bivariate Choropleth Maps: A How-to Guide.” Blog. Josh Stevens.