I have a dummy dataset:
tmp <- structure(list(order = c("John", "John", "John", "Ross", "Ross",
"Ross", "John", "John", "John", "Ross", "Ross", "Ross"), value = c(39,
40, 13, 19, 13, 15, -12, -3, 0, -4, -1, 0), Category = c("VU",
"EN", "CR", "VU", "EN", "CR", "VU", "EN", "CR", "VU", "EN", "CR"
), perc = c(NA, NA, NA, NA, NA, NA, NA, "14%", NA, NA, "9.6%",
NA)), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 25L, 26L, 27L, 28L,
29L, 30L), class = "data.frame")
I would like to display the % on the left of the plot (negative values) on the top of each bar. This is my code:
ggplot(tmp,
aes(fill = Category, y = value, x = reorder(order, value))) +
# add light grey vertical lines in correspondance of x axis thicks
geom_hline(yintercept = c(seq(-20, 0, 5), seq(0, 100, 20)), colour = "grey92") +
# add stacked bars with grey contouring
geom_bar(position = "stack", stat = "identity", alpha = .8, color = "grey50") +
# add zero vertical line
geom_hline(yintercept = 0, colour = "grey50", linewidth = 1.5, linetype = "dashed") +
# add % for negative values
geom_text(aes(label = perc),
hjust = 2,
size = 10) +
# add y axis breaks and limits
scale_y_continuous(breaks = c(seq(-20, 0, 10), seq(0, 100, 20)),
limits = c(-36, 100),
expand = c(0, 0)) +
# add discrete colour scale
scale_fill_manual(values = c("#E55C30FF","#FBB91FFF","#FCFFA4FF")) +
# flip horizontally
coord_flip()
And this is the resulting plot:
As some bars are longer than others, if I play around with hjust
I can just move all the labels at the same time.
Is there a way to have all the labels displayed on top (in this case, on the side, as it's a horizontal barplot) of the bars?
You can achieve your desired result by using position=position_stack()
for the labels too, setting vjust=0
to place the labels inside the bars and finally use hjust = 1
. Also note that I switched to geom_label
as it allows to add some padding around the label, which however requires setting fill=NA
and label.size=0
to get rid of the box around the label. Additionally we have to map on the group
aes.
library(ggplot2)
ggplot(
tmp,
aes(fill = Category, y = value, x = reorder(order, value))
) +
# add light grey vertical lines in correspondance of x axis thicks
geom_vline(xintercept = c(seq(-20, 0, 5), seq(0, 100, 20)), colour = "grey92") +
# add stacked bars with grey contouring
geom_col(alpha = .8, color = "grey50") +
# add zero vertical line
geom_hline(yintercept = 0, colour = "grey50", linewidth = 1.5, linetype = "dashed") +
# add % for negative values
geom_label(
aes(label = perc, group = Category),
hjust = 1,
size = 6,
position = position_stack(vjust = 0),
fill = NA,
label.size = 0
) +
# add y axis breaks and limits
scale_y_continuous(
breaks = c(seq(-20, 0, 10), seq(0, 100, 20)),
limits = c(-36, 100),
expand = c(0, 0)
) +
# add discrete colour scale
scale_fill_manual(values = c("#E55C30FF", "#FBB91FFF", "#FCFFA4FF")) +
# flip horizontally
coord_flip()
#> Warning: Removed 10 rows containing missing values or values outside the scale range
#> (`geom_label()`).