I want to use geom_text_repel to have my labels lie as close to the edge of a pie graph as possible unless the percent is under a certain value, in which case the label should be nudged further away and connected with a line. I adapted a solution from Move labels in ggplot2 pie graph but increased the xpos values for groups above the threshold.
library(dplyr)
library(ggplot2)
library(ggrepel)
library(scales)
threshold = 0.05
age <- data.frame(Age = c("20 - 29", "30 - 39", "40 - 49", "50 - 59", "60 - 69"), count = c(27, 29, 26, 16, 2))
age <- age %>% mutate(percent = count/sum(count),
cs = rev(cumsum(rev(percent))),
ypos = percent/2 + lead(cs, 1),
ypos = ifelse(is.na(ypos), percent/2, ypos),
xpos = ifelse(percent > threshold, 1.8, 1.3),
xn = ifelse(percent > threshold, 0, 0.5))
ggplot(age, aes_string(x = 1, y = "percent", fill = "Age")) +
geom_bar(width = 1 , stat = "identity", colour = "black") +
geom_text_repel(aes(label = percent(percent, accuracy = 0.1), x = xpos, y = ypos), size = 7.5, nudge_x = age$xn, segment.size = .5, direction = "x", force = 0.5, hjust = 1) +
coord_polar("y" , start = 0, clip = "off") +
theme_minimal() +
theme(axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid = element_blank(),
legend.title = element_text(size = 22.5),
legend.text = element_text(size = 19.5),
legend.box.margin=margin(c(0,0,0,30))) +
labs(fill = "Age") +
scale_fill_manual(values = c("#2B83BA", "#FDAE61", "#FFFF99", "#ABDDA4", "#D7191C"))
The below-threshold values act as expected, but the above-threshold values seem to vary in how far they're located from the edge. I believe two things are at play:
- The labels are still being "repelled" despite not being that close to any other labels. This is most evident with the 16.0% label.
- The xpos dictates the position of the centre of the label, but since the labels are horizontal, they might cut into the graph if the label's positioning is to close to the horizontal axis.
How can I account for these two issues? Or if there any any other issues I'd appreciate help in identifying them. I would consider the 29.0% label to be good enough, if others could follow that format.