‘ggasym’ (pronounced “gg-awesome”) plots a symmetric matrix with three different fill aesthetics for the top-left and bottom-right triangles and along the diagonal. It operates within the Grammar of Graphics paradigm implemented in ‘ggplot2’.

author: Joshua H. Cook

date: 2019-02-22

Asymmetric Matrix Plotting in ggplot

Checkout the documentation and vignettes at the pkgdown website https://jhrcook.github.io/ggasym/

For information on using ‘ggplot2’, start here.

Download and Installation

‘ggasym’ is available on CRAN. Use the following command to install.

You can download and install the latest development version from the GitHub repo.


And load the package with the standard library function.


Basic Usage

Here is a basic example. tib is a “tibble” (ie. fancy “data.frame”) of comparisons between groups “A” through “E”. There are two values to be plotted, val_1 and val_2, that hold data on the comparison between g1 and g2. tib is first passed to asymmetrise() to fill in all the missing combinations between g1 and g2 such that the symmetric matrix can be built. All added values take the value NA. The modified data table is finally passed to ggplot() and geom_asymmat() is added on. Here, asymmetrise() added the rows where g1 and g2 are equal, thus will fill the diagonal. I set these values to val_3.

tib <- tibble(g1 = c("A", "A", "A", "A", "B", "B", "B", "C", "C", "D"),
              g2 = c("B", "C", "D", "E", "C", "D", "E", "D", "E", "E"),
              val_1 = seq(1, 10, 1),
              val_2 = rnorm(10, mean = 0, sd = 3))
tib <- asymmetrise(tib, g1, g2)
tib$val_3 <- runif(nrow(tib))
ggplot(tib, aes(x = g1, y = g2)) +
    geom_asymmat(aes(fill_tl = val_1, fill_br = val_2, fill_diag = val_3)) +
    scale_fill_tl_gradient(low = "lightpink", high = "tomato") +
    scale_fill_br_gradient(low = "lightblue1", high = "dodgerblue") +
    scale_fill_diag_gradient(low = "yellow", high = "orange3")

New Aesthetics

The new aesthetics fill_tl, fill_br, and fill_diag behave just like the normal fill, except that they correspond to the top-left (“tl”) and bottom-right (“br”) triangles of the matrix, respectively. This package also includes analogous functions for scaling the fill colors such as scale_fill_tl_gradient2() and scale_fill_br_gradientn() that operate just as expected when using ‘ggplot2’.

ggplot(tib, aes(x = g1, y = g2)) +
    geom_asymmat(aes(fill_tl = val_1, fill_br = val_2, fill_diag = val_3)) +
    scale_fill_tl_gradient(low = "lightpink", high = "tomato") +
    scale_fill_br_gradient2(low = "orange", mid = "white", high = "dodgerblue") +
    scale_fill_diag_gradientn(colors = rainbow(25))

Adjusting Colorbars

Of note, with three colorbars, it may be useful to control their position and other properties. This can be done just like normal in ‘ggplot2’ by passing the correct values to the guide parameter in scale_fill_*_gradient() (original documentation). Below are a few of the options where I put the bars horizontal, adjust the ordering, and put the title above each.


If you have multiple categories, facetting works as expected. The only difference is in the preparation of the data table: you must group_by() the value(s) you will facet by before passing to asymmetrise(). This is shown below.

Grouping first by grps, the tibble is asymmetrized while retaining the grps assignments. I then added values to the diagonal.

Statistical Test Wrapper

I created a wrapper for handling the results of a statistical test to produce a tibble ready to be plotted with ggasym. Here is a brief example - a more detailed example is shown in the vignette “Statistical Test Plotting”. Here I test if the median sale price of houses in Austin, Texas is different between any of the years (for more information on the data source: ?ggplot2::txhousing).

Before plotting, the results of the Tukey post-hoc test are passed to asymmetrise_stats() that prepares the data for geom_asymmat(). The resulting tibble is then plotted and styled in ‘ggplot2’.

Thank yous

I would like to thank the team behind ‘ggplot2’ for creating a flexible and powerful package for the R community.

If you see any mistakes (including small typos) please open an issue and leave a quick statement. Do not worry about appearing annoying.