4

What I want is probably not possible without a lot of work, but maybe someone has a solution. I have a plot like the following (this is an oversimplified example of course) where I have tick labels that fall very close to each other:

dd <- data.frame(x=1:4, y=c(-10,10.5,10.6,10.7),
                 z = LETTERS[1:4])
library(ggplot2)
gg1 <- ggplot(dd, aes(x,y)) +
  geom_point() +
  geom_segment(x=0, aes(xend=x, y=y, yend=y)) +
  scale_y_continuous(breaks=dd$y, labels=dd$z)

plot with three tick labels (B, C, D) overlapping

If I really want to I can export as SVG, dump it into Inkscape, and move the labels apart manually (even adding in little indicator lines connecting the labels with the precise y-axis positions):

picture with B, C, D manually displaced

It would be nice to be able to do something like this programmatically/automatically. I thought about:

  • ggrepel package (only works on labels/text within the plot AFAIK)
  • directlabels package (it has some placement options like "first.bumpup" that might be adaptable/hackable for this case)
  • the n.dodge and check.overlap arguments to guide_axis as illustrated here look useful and interesting, and they almost handle this case, but n.dodge dodges labels horizontally, which will get ugly if the labels are longer than a few characters ...

I would be happy enough with a label.pos.nudge argument that could be specified manually to displace the positions of the labels along the axis from their corresponding

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453

1 Answers1

6

Thanks to the suggestion to look at this question (and this question letting me know about coord_cartesian(clip = "off"), I made the following work (note that I had to change geom_segment(x=0, ...) to geom_segment(x=-Inf, ...) in the base example above, so that turning off clipping didn't mess things up).

gg1 + coord_cartesian(clip = "off") +
  theme(axis.text.y = element_blank(),
        plot.margin = margin(t=5.5, r=5.5, b=5.5, l=30, unit="pt")) +
  geom_text_repel(x = 0.85, aes(label = z, y = y),
                  direction = "y",
                  force_pull = 100,
                  hjust = -7,
                  xlim = c(0.8,1))

graph with repelled points

Note that this may require a fair amount of fussing with plot margins and the arguments of geom_text_repel (force, force_pull, hjust, xlim, etc.) to get it looking right ... I still haven't gotten my real plot just the way I want it, but it's getting close. (It's possible that the x and hjust values are redundant here ...)

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453