Last active
May 2, 2018 21:07
-
-
Save slowkow/003b4d9f3f59cee8551c to your computer and use it in GitHub Desktop.
Repel text labels away from each other in a ggplot2 figure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(ggplot2) | |
library(FField) | |
# You'll have to play with repulsion, cex.x, and cex.y to get satisfactory results. | |
plot_text <- function(x, y, label, repulsion = 1, cex.x = 110, cex.y = 40) { | |
dat <- data.frame(xpos = x, ypos = y, label = label) | |
dat$label <- as.character(dat$label) | |
# Use the FField package to repel the text labels away from each other. | |
dat <- cbind( | |
dat, | |
FFieldPtRep(coords = dat[,c("xpos", "ypos")], rep.fact = repulsion) | |
) | |
# Get the bounding box sizes of the text labels. | |
dat$w <- local({ | |
plot.new() | |
retval <- strwidth(dat$label, cex = cex.x) | |
dev.off() | |
retval | |
}) | |
dat$h <- local({ | |
plot.new() | |
retval <- strheight(dat$label, cex = cex.y) | |
dev.off() | |
retval | |
}) | |
# Feel free to customize this as you wish. | |
ggplot(dat) + | |
# Points for the data. | |
geom_point( | |
aes(x = xpos, y = ypos), | |
size = 4 | |
) + | |
# Line segments connecting the text labels to points. | |
geom_segment( | |
aes(x = xpos, xend = x, y = ypos, yend = y), | |
color = "#666666" | |
) + | |
# White rectangles behind text labels to enhance legibility. | |
geom_rect( | |
aes(xmin = x - w / 2, xmax = x + w / 2, | |
ymin = y - h / 2, ymax = y + h / 2), | |
fill = "white", alpha = 0.5 | |
) + | |
# Text labels. | |
geom_text(aes(x = x, y = y, label = label), size = 8) + | |
theme_bw(base_size = 24) | |
} | |
# Seed for reproducibility. | |
set.seed(43) | |
d <- data.frame( | |
x = runif(10), | |
y = runif(10), | |
label = letters[1:10] | |
) | |
plot_text(d$x, d$y, d$label, repulsion = 0.001, cex.x = 10, cex.y = 20) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(ggplot2) | |
library(wordcloud) | |
# Seed for reproducibility. | |
set.seed(43) | |
d <- data.frame( | |
xpos = runif(10), | |
ypos = runif(10), | |
label = replicate(paste(sample(letters, 6), collapse=""), n = 10) | |
) | |
font.size <- 12 | |
# d <- cbind(d, wordlayout(d$x, d$y, d$label, units = "inches")) | |
d <- cbind(d, wordlayout(d$x, d$y, d$label, units = "figure", cex = font.size / 4)) | |
d$x <- d$x + d$width / 2 | |
d$y <- d$y + d$ht / 2 | |
ggplot(d) + | |
# Points for the data. | |
geom_point( | |
aes(x = xpos, y = ypos), | |
size = 4 | |
) + | |
# Line segments connecting the text labels to points. | |
geom_segment( | |
aes(x = xpos, xend = x, y = ypos, yend = y), | |
color = "#666666" | |
) + | |
# White rectangles behind text labels to enhance legibility. | |
geom_rect( | |
aes(xmin = x - width / 2, xmax = x + width / 2, | |
ymin = y - ht / 2, ymax = y + ht / 2), | |
fill = "blue", alpha = 0.5 | |
) + | |
# Text labels. | |
geom_text(aes(x = x, y = y, label = label), size = font.size) + | |
theme_bw(base_size = 24) |
After exploring the limitations of these packages I decided to make my own package: https://github.com/slowkow/ggrepel
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks to Grigori Kapoustin for the FField package. I learned about
strwidth
andstrheight
from this stackoverflow post.If this does not suit you, please consider some alternatives:
wordlayout
function.Thinking about how to make a new geom or grob...