knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-"
)

R-CMD-check CRAN_Status_Badge Lifecycle: experimental

ggfittext

ggfittext is a ggplot2 extension for fitting text into boxes.

yeats <- data.frame(
  xmin = c(0, 4, 6, 4, 4, 5, 5.5, 5,   5,    5.25, 5.25),
  xmax = c(4, 8, 8, 6, 5, 6, 6,   5.5, 5.25, 5.5,  5.5),
  ymin = c(0, 4, 0, 0, 2, 3, 2,   2,   2.5,  2.75, 2.5),
  ymax = c(8, 8, 4, 2, 4, 4, 3,   2.5, 3,    3,    2.75),
  label = c("<span style='color:red'>T</span><span style='color:orange'>u</span><span style='color:yellow'>r</span><span style='color:green'>n</span><span style='color:blue'>i</span><span style='color:purple'>n</span><span style='color:violet'>g</span>",
            "**and**", "*turning*", "<span style='color:blue'>in</span>", 
            "the<sup>*</sup>", "widening", "gyre", "the",
            "falcon", "cannot", "hear"),
  angle = c(0, 315, 270, 225, 180, 135, 90, 45, 0, 315, 270)
)
library(ggfittext)
library(ggplot2)
library(patchwork)
p1 <- ggplot(yeats, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, label =
                  label, angle = angle)) +
  geom_rect(fill = "grey", colour = "black") +
  geom_fit_text(grow = TRUE, min.size = 0, rich = TRUE)

polar_d <- data.frame(
  word = c("The" , "falcon" , "cannot" , "hear" , "the" , "falconer") ,
  xmin = c( 0.0  , 0.2      , 0.35      , 0.6    , 0.65   , 0.8)        ,
  xmax = c( 0.2  , 0.35     , 0.6      , 0.65    , 0.8   , 1)        ,
  ymin = rep(0, 6),
  ymax = c( 0.95 , 0.85      , 0.75     , 0.65    , 0.45  , 0.35)
)
p2 <- ggplot(polar_d, aes(label = word, xmin = xmin, xmax = xmax, ymin =
                         ymin, ymax = ymax)) +
  geom_rect(aes(xmin = 0, xmax = 1, ymin = 0, ymax = 1)) +
  geom_rect(fill = "lightblue", colour = "black") +
  coord_polar() +
  geom_fit_text(
    grow = TRUE,
    padding.x = grid::unit(1, "mm"),
    padding.y = grid::unit(1, "mm"),
    place = "top",
    min.size = 0
  )
p1 + p2

Installation

Install the release version of ggfittext from CRAN:

install.packages("ggfittext")

If you want the development version, install it from GitHub:

devtools::install_github("wilkox/ggfittext")

Fitting text inside a box

Sometimes you want to draw some text in a ggplot2 plot so that it fits inside a defined area. You can do this by manually fiddling with the font size, but this is tedious and un-reproducible. ggfittext provides a geom called geom_fit_text() that automatically resizes text to fit inside a box. It works like this:

ggplot(animals, aes(x = type, y = flies, label = animal)) +
  geom_tile(fill = "white", colour = "black") +
  geom_fit_text()

As with geom_text(), the position of the text is set by the x and y aesthetics. geom_fit_text() tries to infer the width and height of the box in which the text is allowed to fit, and shrinks down any text that is too big.

Reflowing text

Another way to make the text fit in the box is by reflowing it; that is, wrapping it over multiple lines. With the reflow = TRUE argument, geom_fit_text() will reflow the text before (if still necessary) shrinking it:

ggplot(animals, aes(x = type, y = flies, label = animal)) +
  geom_tile(fill = "white", colour = "black") +
  geom_fit_text(reflow = TRUE)

Growing text

If you want the text to be as large as possible, the argument grow = TRUE will increase the text size to the maximum that will fit in the box. This works well in conjunction with reflow:

ggplot(animals, aes(x = type, y = flies, label = animal)) +
  geom_tile(fill = "white", colour = "black") +
  geom_fit_text(reflow = TRUE, grow = TRUE)

Placing text

By default, text is placed in the centre of the box. However, you can place it in a corner or on a side of the box with the place argument, which takes values like "top", "topright", "bottomleft" and so on:

ggplot(animals, aes(x = type, y = flies, label = animal)) +
  geom_tile(fill = "white", colour = "black") +
  geom_fit_text(place = "topleft", reflow = TRUE)

Bar plots

ggfittext also provides a geom geom_bar_text() for labelling bars in bar plots:

ggplot(altitudes, aes(x = craft, y = altitude, label = altitude)) +
  geom_col() +
  geom_bar_text()

geom_bar_text() works with stacked bar plots:

ggplot(beverages, aes(x = beverage, y = proportion, label = ingredient,
                    fill = ingredient)) +
  geom_col(position = "stack") +
  geom_bar_text(position = "stack", reflow = TRUE)

And it works with dodged bar plots, and with flipped bar plots:

ggplot(beverages, aes(x = beverage, y = proportion, label = ingredient,
                    fill = ingredient)) +
  geom_col(position = "dodge") +
  geom_bar_text(position = "dodge", grow = TRUE, reflow = TRUE, 
                place = "left") +
  coord_flip()

Experimental feature: rich text

With the rich = TRUE argument, geom_fit_text() and geom_bar_text() both support a limited subset of Markdown and HTML markup for text (rendered with gridtext).

ggplot(animals_rich, aes(x = type, y = flies, label = animal)) +
  geom_tile(fill = "white", colour = "black") +
  geom_fit_text(reflow = TRUE, grow = TRUE, rich = TRUE)

Rich text cannot be drawn in polar coordinates. Please note that this feature is liable to change, and is subject to upstream changes to gridtext.

Specifying the box limits

If you want to manually set the limits of the box (instead of having them inferred from x and y), you can use xmin & xmax and/or ymin & ymax:

ggplot(presidential, aes(ymin = start, ymax = end, x = party, label = name)) +
  geom_fit_text(grow = TRUE) +
  geom_errorbar(alpha = 0.5)

Alternatively, you can set the width and/or height with the width and/or height arguments, which should be grid::unit() objects. The horizontal and/or vertical centre of the box will be defined by x and/or y.

Experimental feature: text in polar coordinates

Text can be drawn in polar coordinates with geom_fit_text() simply by adding coord_polar() to the plot. This feature is experimental and any bug reports are very welcome.

p <- ggplot(gold, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, 
                 fill = linenumber, label = line)) +
  coord_polar() +
  geom_rect() +
  scale_fill_gradient(low = "#fee391", high = "#238443")

p + geom_fit_text(min.size = 0, grow = TRUE)

When text is drawn in polar coordinates, the flip = TRUE argument can be used to flip upside-down text the 'right way up' to ease readability:

p + geom_fit_text(min.size = 0, grow = TRUE, flip = TRUE)

Other useful arguments

All arguments to geom_fit_text() can also be used with geom_bar_text().

ggplot(animals, aes(x = type, y = flies, fill = mass, label = animal)) +
  geom_tile() +
  geom_fit_text(reflow = TRUE, grow = TRUE, contrast = TRUE)
ggplot(data.frame(label = "fullheight = TRUE", xmin = 0.25, xmax = 0.75, ymin = 0.25, ymax = 0.75), 
       aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, label = label)) +
  geom_rect() +
  geom_fit_text(grow = TRUE, fullheight = TRUE, family = "mono") +
  theme(axis.text = element_blank(), axis.ticks = element_blank(), panel.background = element_blank(), plot.title = element_text(hjust = 0.5))
ggplot(data.frame(label = "fullheight = FALSE", xmin = 0.25, xmax = 0.75, ymin = 0.25, ymax = 0.75), 
       aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, label = label)) +
  geom_rect() +
  geom_fit_text(grow = TRUE, fullheight = FALSE, family = "mono") +
  theme(axis.text = element_blank(), axis.ticks = element_blank(), panel.background = element_blank(), plot.title = element_text(hjust = 0.5))


wilkox/ggfittext documentation built on Feb. 7, 2024, 1:30 p.m.