|
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 comment has been minimized.
Thanks to Grigori Kapoustin for the FField package. I learned about
strwidthandstrheightfrom this stackoverflow post.If this does not suit you, please consider some alternatives:
wordlayoutfunction.Thinking about how to make a new geom or grob...