Hands-on Exercise 5a: Creating Ternary Plot with R

Author

Vanessa Heng

Published

February 6, 2024

Modified

March 5, 2024

1 Overview

Ternary plots are a way of displaying the distribution and variability of three-part compositional data. (For example, the proportion of aged, economy active and young population or sand, silt, and clay in soil.) It’s display is a triangle with sides scaled from 0 to 1. Each side represents one of the three components. A point is plotted so that a line drawn perpendicular from the point to each leg of the triangle intersect at the component values of the point.

We will learn how to build ternary plot programmatically using R for visualising and analysing population structure of Singapore.

The hands-on exercise consists of four steps:

  • Install and launch tidyverse and ggtern packages.

  • Derive three new measures using mutate() function of dplyr package.

  • Build a static ternary plot using ggtern() function of ggtern package.

  • Build an interactive ternary plot using plot-ly() function of Plotly R package.

2 Getting Started

2.1 Installing and loading the packages

For this exercise, the following R packages will be used.

  • ggtern, a ggplot extension, specially designed to plot ternary diagrams. The package will be used to plot static ternary plots.

  • Plotly R, an R package for creating interactive web-based graphs via plotly’s JavaScript graphing library, plotly.js . The plotly R libary contains the ggplotly function, which will convert ggplot2 figures into a Plotly object.

pacman::p_load(plotly, ggtern, tidyverse)

2.2 Data import

The Singapore Residents by Planning AreaSubzone, Age Group, Sex and Type of Dwelling, June 2000-2018 data will be used.

pop_data <- read_csv("data/respopagsex2000to2018_tidy.csv") 

2.3 Preparing the Data

The population data needs to be presented in a different way.

Let’s use the mutate() function of dplyr package to derive three new measures, namely:

  • young: 0 - 24 years old

  • active: 25 - 64 years old

  • old: 65 years old and above

The data is filtered for 2018.

agpop_mutated <- pop_data %>%
# change year column from numeric to character
  mutate(`Year` = as.character(Year))%>%
#spread the age column to multiple age-category columns
  spread(AG, Population) %>%
  mutate(YOUNG = rowSums(.[4:8]))%>%
  mutate(ACTIVE = rowSums(.[9:16]))  %>%
  mutate(OLD = rowSums(.[17:21])) %>%
  mutate(TOTAL = rowSums(.[22:24])) %>%
  filter(Year == 2018)%>%
  filter(TOTAL > 0)

3 Plotting Ternary Diagram with R

Use ggtern() function of ggtern package to create a simple ternary plot.

Show the code
ggtern(data = agpop_mutated, 
       aes(x = YOUNG,y = ACTIVE, z = OLD)) +   
  geom_point()
Show the code
ggtern(data = agpop_mutated,         
       aes(x = YOUNG,y = ACTIVE, z = OLD)) +   
  geom_point() +   
  labs(title="Population structure of Singpore in 2018") +   
  theme_rgbw()
Show the code
# reusable function for creating annotation object
label <- function(txt) {
  list(text = txt, 
    x = 0.1, y = 1,
    ax = 0, ay = 0,
    xref = "paper", yref = "paper", 
    align = "center",
    font = list(family = "serif", 
                size = 15, color = "white"),
    bgcolor = "#b3b3b3", bordercolor = "black", 
    borderwidth = 2) 
  }

# reusable function for axis formatting
axis <- function(txt) {
  list(title = txt, tickformat = ".0%", 
       tickfont = list(size = 10))
}

ternaryAxes <- list(
  aaxis = axis("Active"), 
  baxis = axis("Young"), 
  caxis = axis("Old")
)

# Initiating a plotly visualization 
plot_ly(agpop_mutated, 
          a = ~ACTIVE, 
          b = ~YOUNG, 
          c = ~OLD, 
          color = I("black"), 
          type = "scatterternary") %>%
  layout(annotations = label("Ternary Markers"), ternary = ternaryAxes)