ggrepel examples

library(knitr)
opts_chunk$set(
  cache       = TRUE,
  autodep     = TRUE,
  echo        = FALSE,
  warning     = FALSE,
  error       = FALSE,
  message     = FALSE,
  out.width   = 700,
  fig.width   = 12,
  fig.height  = 8,
  dpi         = 300,
  cache.path  = "cache/ggrepel/",
  fig.path    = "figures/ggrepel/",
  pngquant    = "--speed=1 --quality=0-10",
  concordance = TRUE
)
knit_hooks$set(
  pngquant = hook_pngquant
)
library(gridExtra)
library(ggplot2)
theme_set(theme_classic(base_size = 18) %+replace% theme(
  axis.line.y = element_line(colour = "black", size = 0.2),
  axis.line.x = element_line(colour = "black", size = 0.2),
  axis.ticks = element_line(colour = "black", size = 0.2)
))

Overview

ggrepel provides geoms for ggplot2 to repel overlapping text labels:

Text labels repel away from each other, away from data points, and away from edges of the plotting area.

Let's compare geom_text() and geom_text_repel():

library(ggrepel)
set.seed(42)

dat <- subset(mtcars, wt > 2.75 & wt < 3.45)
dat$car <- rownames(dat)

p <- ggplot(dat, aes(wt, mpg, label = car)) +
  geom_point(color = "red")

p1 <- p + geom_text() + labs(title = "geom_text()")

p2 <- p + geom_text_repel() + labs(title = "geom_text_repel()")

gridExtra::grid.arrange(p1, p2, ncol = 2)

Installation

ggrepel version r packageVersion("ggrepel") is available on CRAN:

install.packages("ggrepel")

The latest development version may have new features, and you can get it from GitHub:

# Use the devtools package
# install.packages("devtools")
devtools::install_github("slowkow/ggrepel")

# Or use the install-github.me service
source("https://install-github.me/slowkow/ggrepel")

Options

Options available for geom_text() and geom_label() are also available for geom_text_repel() and geom_label_repel(), including size, angle, family, fontface, etc.

ggrepel provides additional options for geom_text_repel and geom_label_repel:

|Option | Default | Description |--------------- | --------- | ------------------------------------------------ |force | 1 | force of repulsion between overlapping text labels |direction | "both" | move text labels "both" (default), "x", or "y" directions |max.iter | 2000 | maximum number of iterations to try to resolve overlaps |nudge_x | 0 | adjust the starting x position of the text label |nudge_y | 0 | adjust the starting y position of the text label |box.padding | 0.25 lines | padding around the text label |point.padding | 0 lines | padding around the labeled data point |segment.color | "black" | line segment color |segment.size | 0.5 mm | line segment thickness |segment.alpha | 1.0 | line segment transparency |arrow | NULL | render line segment as an arrow with grid::arrow()

Examples

Hide some of the labels

Set labels to the empty string "" to hide them. All data points repel the non-empty labels.

set.seed(42)

dat2 <- subset(mtcars, wt > 3 & wt < 4)
# Hide all of the text labels.
dat2$car <- ""
# Let's just label these items.
ix_label <- c(2,3,16)
dat2$car[ix_label] <- rownames(dat2)[ix_label]

ggplot(dat2, aes(wt, mpg, label = car)) +
  geom_point(color = ifelse(dat2$car == "", "grey50", "red")) +
  geom_text_repel()

Do not repel labels from data points

Set point.padding = NA to prevent label repulsion away from data points.

Now labels move away from each other and away from the edges of the plot.

set.seed(42)
ggplot(dat, aes(wt, mpg, label = car)) +
  geom_point(color = "red") +
  geom_text_repel(point.padding = NA)

Limit labels to a specific area

Use options xlim and ylim to constrain the labels to a specific area. Limits are specified in data coordinates. Use NA when there is no lower or upper bound in a particular direction.

Here we also use grid::arrow() to render the segments as arrows.

set.seed(42)

# All labels should be to the right of 3.
x_limits <- c(3, NA)

ggplot(dat, aes(wt, mpg, label = car, color = factor(cyl))) +
  geom_vline(xintercept = x_limits, linetype = 3) +
  geom_point() +
  geom_label_repel(
    arrow = arrow(length = unit(0.03, "npc"), type = "closed", ends = "first"),
    force = 10,
    xlim  = x_limits
  ) +
  scale_color_discrete(name = "cyl")

Align labels on the top or bottom edge

Use hjust or vjust to justify the text neatly:

Sometimes the labels do not align perfectly. Try using direction = "x" to limit label movement to the x-axis (left and right) or direction = "y" to limit movement to the y-axis (up and down). The default is direction = "both".

Also try using xlim() and ylim() to increase the size of the plotting area so all of the labels fit comfortably.

set.seed(42)

ggplot(mtcars, aes(x = wt, y = 1, label = rownames(mtcars))) +
  geom_point(color = "red") +
  geom_text_repel(
    nudge_y      = 0.05,
    direction    = "x",
    angle        = 90,
    vjust        = 0,
    segment.size = 0.2
  ) +
  xlim(1, 6) +
  ylim(1, 0.8) +
  theme(
    axis.line.y  = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.y  = element_blank(),
    axis.title.y = element_blank()
  )

Align text vertically with nudge_y and allow the labels to move horizontally with direction = "x":

set.seed(42)

dat <- mtcars
dat$car <- rownames(dat)

ggplot(dat, aes(qsec, mpg, label = car)) +
  geom_text_repel(
    data          = subset(dat, mpg > 30),
    nudge_y       = 36 - subset(dat, mpg > 30)$mpg,
    segment.size  = 0.2,
    segment.color = "grey50",
    direction     = "x"
  ) +
  geom_point(color = ifelse(dat$mpg > 30, "red", "black")) +
  scale_x_continuous(expand = c(0.05, 0.05)) +
  scale_y_continuous(limits = c(NA, 36))

Align labels on the left or right edge

Set direction to "y" and try hjust 0.5, 0, and 1:

set.seed(42)

p <- ggplot(mtcars, aes(y = wt, x = 1, label = rownames(mtcars))) +
  geom_point(color = "red") +
  ylim(1, 5.5) +
  theme(
    axis.line.x  = element_blank(),
    axis.ticks.x = element_blank(),
    axis.text.x  = element_blank(),
    axis.title.x = element_blank(),
    plot.title   = element_text(hjust = 0.5)
  )

p1 <- p +
  xlim(1, 1.375) +
  geom_text_repel(
    nudge_x      = 0.15,
    direction    = "y",
    hjust        = 0,
    segment.size = 0.2
  ) +
  ggtitle("hjust = 0")

p2 <- p + 
  xlim(1, 1.375) +
  geom_text_repel(
    nudge_x      = 0.2,
    direction    = "y",
    hjust        = 0.5,
    segment.size = 0.2
  ) +
  ggtitle("hjust = 0.5 (default)")

p3 <- p +
  xlim(0.25, 1) +
  scale_y_continuous(position = "right") +
  geom_text_repel(
    nudge_x      = -0.35,
    direction    = "y",
    hjust        = 1,
    segment.size = 0.2
  ) +
  ggtitle("hjust = 1")

gridExtra::grid.arrange(p1, p2, p3, ncol = 3)

Align text horizontally with nudge_x and hjust, and allow the labels to move vertically with direction = "y":

set.seed(42)

dat <- subset(mtcars, wt > 2.75 & wt < 3.45)
dat$car <- rownames(dat)

ggplot(dat, aes(wt, mpg, label = car)) +
  geom_text_repel(
    data          = subset(dat, wt > 3),
    nudge_x       = 3.5 - subset(dat, wt > 3)$wt,
    segment.size  = 0.2,
    segment.color = "grey50",
    direction     = "y",
    hjust         = 0
  ) +
  geom_text_repel(
    data          = subset(dat, wt < 3),
    nudge_x       = 2.7 - subset(dat, wt < 3)$wt,
    segment.size  = 0.2,
    segment.color = "grey50",
    direction     = "y",
    hjust         = 1
  ) +
  scale_x_continuous(
    breaks = c(2.5, 2.75, 3, 3.25, 3.5),
    limits = c(2.4, 3.8)
  ) +
  geom_point(color = "red")

Polar coordinates

set.seed(42)

mtcars$label <- rownames(mtcars)
mtcars$label[mtcars$mpg < 25] <- ""

ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl), label = label)) +
  coord_polar(theta = "x") +
  geom_point(size = 2) +
  scale_color_discrete(name = "cyl") +
  geom_text_repel(show.legend = FALSE) + # Don't display "a" in the legend.
  theme_bw(base_size = 18)

Mathematical expressions

d <- data.frame(
  x    = c(1, 2, 2, 1.75, 1.25),
  y    = c(1, 3, 1, 2.65, 1.25),
  math = c(
    NA,
    "integral(f(x) * dx, a, b)",
    NA,
    "lim(f(x), x %->% 0)",
    NA
  )
)

ggplot(d, aes(x, y, label = math)) +
  geom_point() +
  geom_label_repel(
    parse       = TRUE, # Parse mathematical expressions.
    size        = 8,
    box.padding = 2
  )

Animation

# This chunk of code will take a minute or two to run.
library(ggrepel)
library(animation)

plot_frame <- function(n) {
  set.seed(42)
  p <- ggplot(mtcars, aes(wt, mpg, label = rownames(mtcars))) +
    geom_point(color = "red") +
    geom_text_repel(
      size = 5, force = 3, max.iter = n
    ) +
    theme_minimal(base_size = 16)
  print(p)
}

saveGIF(
  lapply(ceiling(1.75^(1:12)), function(i) {
    plot_frame(i)
  }),
  interval   = 0.20,
  ani.width  = 800,
  ani.heigth = 600,
  movie.name = "animated.gif"
)

Click here to see the animation.

Source code

View the source code for this vignette on GitHub.

R Session Info

sessionInfo()


Try the ggrepel package in your browser

Any scripts or data that you put into this service are public.

ggrepel documentation built on May 9, 2018, 5:04 p.m.