I'm working on a chart similar to a slopegraph, where I'd like to put labels along one or both sides with ample blank space to fit them on both sides. In cases where labels are very long, I've wrapped them using stringr::str_wrap
to place linebreaks. To keep labels from overlapping, I'm using ggrepel::geom_text_repel
with direction = "y"
so the x-positions are stable but the y-positions are repelled away from one another. I've also got hjust = "outward"
to align the left-side text at its right end and vice versa.
However, it seems that the repel positioning places the label's bounding box with an hjust = "outward"
, but the text within that label has hjust = 0.5
, i.e. text is centered within its bounds. Until now, I'd never noticed this, but with wrapped labels, the second line is awkwardly centered, whereas I'd expect to see both lines left-aligned or right-aligned.
Here's an example built off the mpg
dataset.
library(ggplot2)
library(dplyr)
library(ggrepel)
df <- structure(list(long_lbl = c("chevrolet, k1500 tahoe 4wd, auto(l4)",
"chevrolet, k1500 tahoe 4wd, auto(l4)", "subaru, forester awd, manual(m5)",
"subaru, forester awd, manual(m5)", "toyota, camry, manual(m5)",
"toyota, camry, manual(m5)", "toyota, toyota tacoma 4wd, manual(m5)",
"toyota, toyota tacoma 4wd, manual(m5)", "volkswagen, jetta, manual(m5)",
"volkswagen, jetta, manual(m5)"), year = c(1999L, 2008L, 1999L,
2008L, 1999L, 2008L, 1999L, 2008L, 1999L, 2008L), mean_cty = c(11,
14, 18, 20, 21, 21, 15, 17, 33, 21)), class = c("tbl_df", "tbl",
"data.frame"), row.names = c(NA, -10L))
df_wrap <- df %>%
mutate(wrap_lbl = stringr::str_wrap(long_lbl, width = 25))
ggplot(df_wrap, aes(x = year, y = mean_cty, group = long_lbl)) +
geom_line() +
geom_text_repel(aes(label = wrap_lbl),
direction = "y", hjust = "outward", seed = 57, min.segment.length = 100) +
scale_x_continuous(expand = expand_scale(add = 10))
The same thing happens with other values of hjust
. Looking at the function's source, I see a line that points to this issue:
hjust = x$data$hjust %||% 0.5,
where %||%
assigns 0.5 if x$data$hjust
is null. That's as far as I understand, but it seems that the hjust
I've set isn't being carried over to this positioning and is instead coming up null.
Have I missed something? Can anyone see where I might override this without reimplementing the whole algorithm? Or is there a bug here that drops my hjust
?
See Question&Answers more detail:
os