The Mad Hatter’s Guide to Data Viz and Stats in R
  1. Data Viz and Stats
  2. Arts
  3. Scales
  • Data Viz and Stats
    • Tools
      • Introduction to R and RStudio
    • Studio Flow and Data Kits
      • 12-Day Studio Index
      • Healthcare Data Kits
    • Visualization
      • Data
      • Inspect Data
      • Graphs
      • Summaries
      • Counts
      • Quantities
      • Groups
      • Distributions
      • Groups and Distributions
      • Change
      • Proportions
      • Hierarchy
      • Evolution and Flow
      • Ratings and Rankings
      • Surveys
      • Time
      • Space
        • Introduction to Maps
        • What is Vector Data?
        • The Grammar of Maps
        • Interactive Maps with leaflet
      • Networks
      • Miscellaneous Graphing Tools, and References
    • Inference
      • Basics
      • 🎲 Samples
      • Randomization
      • One Mean
      • Two Independent Means
      • Two Paired Means
      • Multiple Means (ANOVA)
      • Correlation
      • One Proportion
      • Two Proportions
    • Modelling
      • Linear Regression
      • Logistic Regression
      • 🕔 Time Series
    • Workflow
      • Facing the Abyss
      • I Publish, therefore I Am
      • Data Carpentry
    • Arts
      • Colours
      • Fonts for Charts
      • Font Effects in Charts
      • Branding and Typography
      • Annotations
      • More Annotations
      • Highlighting
      • Scales
    • AI Tools
      • Using gander and ellmer
      • Using Github Copilot and other AI tools to generate R code
      • Using LLMs to Explain Stat models
    • Case Studies
      • Demo:Product Packaging and Elderly People
      • Ikea Furniture
      • Movie Profits
      • Gender at the Work Place
      • Heptathlon
      • School Scores
      • Children's Games
      • Valentine’s Day Spending
      • Women Live Longer?
      • Hearing Loss in Children
      • California Transit Payments
      • Seaweed Nutrients
      • Coffee Flavours
      • Legionnaire’s Disease in the USA
      • Antarctic Sea ice
      • William Farr's Observations on Cholera in London
    • Projects
      • No Free Hunch

On this page

  • 1 Setting up R Packages
  • 2 Introduction
  • 3 Scales: Breaks and Labels
  • 4 Case Study: gss-wages
    • 4.1 Basic Plots
  • 5 Case Study: Gapminder
  • 6 References
  1. Data Viz and Stats
  2. Arts
  3. Scales

Scales

Percentages, Ratios, and such like

Published

August 30, 2025

Modified

October 21, 2026

1 Setting up R Packages

library(tidyverse)
library(ggformula)

library(scales) ## scale functions for visualization. Part of tidyverse.

2 Introduction

We may have been using ggplot2 for a while now, learning how to add fonts, colours, and annotations. Here we will look at changing the scales on the axes of our graphs and plots. Scales such as percentages, ratios, and other such like are needed when the quantities depicted demand it, when the data variabls on the axes are not simple counts or measurements.

Here we will look at some of the neatfeatures from the scales package.

3 Scales: Breaks and Labels

The scales package provides functions that are useful for scaling axes and legends in ggplot2. It is part of the tidyverse and is automatically loaded when you load ggplot2.

There are several parts to scaling: the breaks, the labels, and the transformations.

Breaks: These are the points at which ticks appear on an axis. You can specify breaks manually or use functions to generate them automatically.

Labels: These are the text labels that appear at the breaks. You can customize the labels to display values in different formats, such as percentages, currency, dates, or scientific notation.

Transformations: These are functions that can be applied to the data before plotting, such as logarithmic or square root transformations.

Scales can be applied all the aesthetics in ggplot: x, y, color, fill, size, shape, and even some esoteric ones area, alpha, linewidth etc.

4 Case Study: gss-wages

We will work with datasets that we have seen in earlier modules, datasets that deal with variables like currencies, or which vary over several multiples.

Let us take an income dataset from Vincent Arel-Bundock’s website.. We will use the dataset gss_wages which is available here.https://vincentarelbundock.github.io/Rdatasets/csv/stevedata/gss_wages.csv

As always, we will start with a table of the data:

gss_wages <- read_csv("https://vincentarelbundock.github.io/Rdatasets/csv/stevedata/gss_wages.csv") %>% drop_na()

gss_wages
Table 1: GSS Wages Dataset

4.1 Basic Plots

Let us create a basic scatter plot of realrinc vs year and colour by gender, and another boxplot of realrinc by gender:

Show the Code
p1 <- gf_point(
  data = gss_wages, realrinc ~ year,
  color = ~gender, alpha = 0.8, size = 1
) %>%
  gf_labs(y = "Income", x = "Year", title = "GSS-Wages Dataset") %>%
  gf_refine(scale_color_brewer(palette = "Set1"))
p1

p2 <- gf_boxplot(
  data = gss_wages, realrinc ~ gender,
  color = ~gender, fill = ~gender,
  alpha = 0.8, orientation = "x"
) %>%
  gf_labs(
    y = "Income", x = "Gender",
    title = "GSS-Wages Dataset"
  ) %>%
  gf_refine(scale_color_brewer(palette = "Set1"))
p2
(a) Scatter Plot
(b) Box Plot
Figure 1: Basic Plots

Note the somewhat unwieldy y-axes in the plots! Let us now change the y-axis to show income in thousands of dollars. We will use the scales package for this.

Show the Code
p1 %>%
  gf_refine(scale_y_continuous(labels = scales::label_currency(scale = 0.001, suffix = "K"))) |>
  gf_labs(subtitle = "Note Dollar Currency Scale on y-axis")



p2 %>%
  gf_refine(scale_y_continuous(labels = scales::label_currency(scale = 0.001, suffix = "K"))) |>
  gf_labs(subtitle = "Note Dollar Currency Scale on y-axis")
(a) Scatter Plot
(b) Box Plot
Figure 2: Dollar Scale with Automatic Breaks

The scale function label_currency has several arguments that can be used to customize the display of currency values. Here we have used scale = 0.001 to convert the values to thousands and suffix = "K" to add a “K” suffix to the labels.

Note that the y-axis scale is linear!! We may yet be dissatisfied with this plot and wish to change the y-axis to a logarithmic scale. This is useful when the data spans several orders of magnitude, as is often the case with man-made variables such as income data. We will also, for demonstration purposes, setup an excessively detailed y-scale with far too many breaks and remedy that in the other plot!!

p1 %>%
  gf_refine(scale_y_log10(
    labels = scales::label_currency(scale = 0.001, suffix = "K"),
    breaks = scales::breaks_log(n = 20, base = 10)
  )) |>
  gf_labs(subtitle = "Note Log Scale on y-axis")
p2 %>%
  gf_refine(scale_y_log10(
    labels = scales::label_currency(scale = 0.001, suffix = "K", ),
    breaks = scales::breaks_log(n = 5, base = 10)
  )) |>
  gf_labs(subtitle = "Note Log Scale on y-axis")
(a) Scatter Plot (Excessive Breaks)
(b) Box Plot (Fewer Breaks )
Figure 3: Logarithmic Dollar Scale with (Excessively ) Detailed Breaks

5 Case Study: Gapminder

We will work with the gapminder dataset from the gapminder package. This dataset contains data on life expectancy, GDP per capita, and population for various countries over several years.

gapminder <- gapminder::gapminder
gapminder
Table 2: Gapminder Dataset

There are several variables, most of them “man-made”, which tend to vary over several orders of magnitude. Let us see how we can depict those.

p1 <- gf_point(
  data = gapminder, gdpPercap ~ year,
  color = ~continent, alpha = 0.8, size = 1
) %>%
  gf_labs(y = "GDP per Capita", x = "Year", title = "Gapminder Dataset") %>%
  gf_refine(scale_color_brewer(palette = "Set1"))
p1
p2 <- gf_boxplot(
  data = gapminder, gdpPercap ~ continent,
  color = ~continent, fill = ~continent,
  alpha = 0.8, orientation = "x"
) %>%
  gf_labs(y = "GDP per Capita", x = "Continent", title = "Gapminder Dataset") %>%
  gf_refine(scale_color_brewer(palette = "Set1"))

p2
(a) Scatter Plot
(b) Box Plot
Figure 4: Basic Gapminder Plot

Let us convert the y-axis to show a scale in USD.

Show the Code
p1 %>%
  gf_refine(scale_y_continuous(labels = scales::label_currency(scale = 0.001, suffix = "K"))) |>
  gf_labs(subtitle = "Note Dollar Currency Scale on y-axis")


p2 %>%
  gf_refine(scale_y_continuous(labels = scales::label_currency(scale = 0.001, suffix = "K"))) |>
  gf_labs(subtitle = "Note Dollar Currency Scale on y-axis")
(a) Scatter Plot
(b) Box Plot
Figure 5: Dollar Scale with Automatic Breaks

Note that the Y-axis is still linear here. No transformation applied!

And population?

Show the Code
p1 <- gf_point(
  data = gapminder, pop ~ year,
  color = ~continent,
  alpha = 0.8, size = 1
) %>%
  gf_labs(
    y = "Population", x = "Year",
    title = "Gapminder Dataset"
  ) %>%
  gf_refine(scale_color_brewer(palette = "Set1"))
p1
#####
p2 <- gf_boxplot(
  data = gapminder, pop ~ continent,
  color = ~continent, fill = ~continent,
  alpha = 0.8, orientation = "x"
) %>%
  gf_labs(
    y = "Population", x = "Continent",
    title = "Gapminder Dataset"
  ) %>%
  gf_refine(scale_color_brewer(palette = "Set1"))

p2
(a) Scatter Plot
(b) Box Plot
Figure 6: Basic Gapminder Plot

Hmmm….can we plot the y-axis in multiples? Like, 1X, 2X…..10X….100X? We wish to implement scales for data that have geometric progression, where the variable of interest spans several multiples, i.e. \frac{max_y}{min_y} \gg 1000. for example.

Show the Code
#|
unit <- 1e7 # 1X = 10 million

p1 %>%
  gf_refine(
    scale_x_continuous(breaks = seq(1950, 2010, 10)),
    scale_y_continuous(
      name = "Population (X = 10 million)",
      transform = "log10",
      breaks = c(0.1, 0.5, 1, 5, 10, 50, 100) * unit,
      labels = scales::label_number(
        scale = 1 / unit,
        suffix = "X"
      ),
      expand = expansion(mult = c(0.25, 0.25))
    )
  ) |>
  gf_labs(subtitle = "Note the log scale on the y-axis")

p2 %>%
  gf_refine(
    scale_y_continuous(
      name = "Population (X = 10 million)",
      transform = "log10",
      breaks = c(0.1, 0.5, 1, 5, 10, 50, 100) * unit,
      labels = scales::label_number(
        scale = 1 / unit,
        suffix = "X"
      ),
      expand = expansion(mult = c(0.25, 0.25))
    )
  ) |>
  gf_labs(subtitle = "Note the log scale on the y-axis")
(a) Scatter Plot
(b) Box Plot
Figure 7: Ratiometric Scale

Try commenting our the transform = "log10" in the code above and see how the graphs change!

For a complex use of the scales package, where we use more than one y-axis, head off to this Case Study: Legionnaire’s Disease in the USA. Try to understand the code there and replicate!!

6 References

  1. R package scales: https://scales.r-lib.org/
R Package Citations
Package Version Citation
scales 1.4.0 Wickham et al. (2025)
Wickham, Hadley, Thomas Lin Pedersen, and Dana Seidel. 2025. scales: Scale Functions for Visualization. https://doi.org/10.32614/CRAN.package.scales.
Back to top
Highlighting
Assembling a Collage of Plots

License: CC BY-SA 2.0

Website made with ❤️ and Quarto, by Arvind V.

Hosted by Netlify .