Skip to content
Bivariate Mapping with ggplot2
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
.travis add full linux sf building script Apr 23, 2019
R spell check Apr 29, 2019
docs add hex to README and pkdown site May 3, 2019
inst/extdata expand testing for bi_pal Apr 29, 2019
man add hex to README and pkdown site May 3, 2019
.Rbuildignore finish draft testing of bi_pal Apr 29, 2019
.travis.yml add caching into travis again May 3, 2019
CRAN-RELEASE second resubmission May 4, 2019
DESCRIPTION edit description May 4, 2019
NAMESPACE fix missing rel function Apr 29, 2019 update DESCRIPTION and NEWS May 3, 2019
README.Rmd add hex to README and pkdown site May 3, 2019 add hex to README and pkdown site May 3, 2019
_pkgdown.yml re-organize references on pkgdown site Apr 29, 2019
biscale.Rproj initial pkg infrastructure Apr 23, 2019
codecov.yml enable ci Apr 23, 2019 edit description May 4, 2019
index.Rmd add hex to README and pkdown site May 3, 2019


lifecycle Travis-CI Build Status AppVeyor Build Status Coverage status DOI CRAN_status_badge

biscale implements a set of functions for bivariate thematic mapping based on the tutorial written by Timo Grossenbacher and Angelo Zehr as well as a set of bivariate mapping palettes from Joshua Stevens’s tutorial. The package currently supports two-by-two and three-by-three bivariate maps:

In addition to support for both two-by-two and three-by-three maps, the package also supports four methods for calculating breaks for bivariate maps.


Since the package does not directly use functions from sf, it is a suggested dependency rather than a required one. However, the most direct approach to using biscale is with sf objects, and we therefore recommend users install sf before proceeding with using biscale. Windows users should be able to install sf without significant issues, but macOS and Linux users will need to install several open source spatial libraries to get sf itself up and running. The easiest approach for macOS users is to install the GDAL 2.0 Complete framework from Kyng Chaos.

For Linux users, steps will vary based on the flavor being used. Our configuration file for Travis CI and its associated bash script should be useful in determining the necessary components to install.

Once sf is installed, the easiest way to get biscale is to install it from CRAN:


Alternatively, the development version of biscale can be accessed from GitHub with remotes:

# install.packages("remotes")


Quick Overview

Creating bivariate plots in the style described by Grossenbacher and Zehr requires a number of dependencies in addition to biscale - ggplot2 for plotting, cowplot for combining the legend and the main map, and sf for working with spatial objects in R:

# load dependencies

The biscale package comes with some sample data from St. Louis, MO that you can use to check out the bivariate mapping workflow. Our first step is to create our classes for bivariate mapping. biscale currently supports a both two-by-two and three-by-three tables of classes, created with the bi_class() function: :

# create classes
data <- bi_class(stl_race_income, x = pctWhite, y = medInc, style = "quantile", dim = 3)

The default method for calculating breaks is "quantile", which will provide breaks at 33.33% and 66.66% percent (i.e. tercile breaks) for three-by-three palettes. Other options are "equal", "fisher", and "jenks". These are specified with the optional style argument. The dim argument is used to adjust whether a two-by-two and three-by-three tables of classes is returned

Once breaks are created, we can use bi_scale_fill() as part of our ggplot() call:

# create map
map <- ggplot() +
  geom_sf(data = data, aes(fill = bi_class), color = "white", size = 0.1, show.legend = FALSE) +
  bi_scale_fill(pal = "DkBlue", dim = 3) +
    title = "Race and Income in St. Louis, MO",
    subtitle = "Dark Blue (DkBlue) Palette"
  ) +

Other options for palettes include "Brown", "DkCyan", "DkViolet", and "GrPink". The bi_theme() function applies a simple theme without distracting elements, which is preferable given the already elevated complexity of a bivarite map. We need to specify the dimensions of the palette for bi_scale_fill() as well.

To add a legend to our map, we need to create a second ggplot object. We can use bi_legend() to accomplish this, which allows us to easily specify the fill palette, the x and y axis labels, and their size along with the dimensions of the palette:

legend <- bi_legend(pal = "DkBlue",
                    dim = 3,
                    xlab = "Higher % White ",
                    ylab = "Higher Income ",
                    size = 8)

Note that plotmath is used to draw the arrows since Unicode arrows are font dependent. This happens internally as part of bi_legend() - you don’t need to include them in your xlab and ylab arguments!

With our legend drawn, we can then combine the legend and the map with cowplot. The values needed for this stage will be subject to experimentation depending on the shape of the map itself.

# combine map with legend
finalPlot <- ggdraw() +
  draw_plot(map, 0, 0, 1, 1) +
  draw_plot(legend, 0.2, .7, 0.2, 0.2)

Breaks for Bivariate Mapping

The map at the top of the README uses the default "quantile" style for calculating breaks. The other options, "equal", "fisher", and "jenks", will produce narrower ranges for the percent white variable in particular:

Palettes for Bivariate Mapping

In addition to the "DkBlue" palette show in the first map, there are a number of other options for palettes (including "Brown", which is not shown here) for two-by-two mapping:

These same options exist for three-by-three mapping as well:

All color palettes, including "Brown", can be previewed by using the bi_pal() function or by checking out that function’s documentation on the package website.

Contributor Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

You can’t perform that action at this time.