In this post, we will learn how to properly annotate a bars barplot, where there are both positive and negative values/bars in ggplot2. In ggplot2, we can use gem_text() with label option to annotate text or bar heights on a barplot easily. However, when we have a barplot that has both positive and negative bars, We would live to annotate text/values such that it perfectly aligns with the bar heights. The simple attempt to annotate using geom_text() will not result in correctly aligned values.
library(tidyverse) library(palmerpenguin) library(broom) theme_set(theme_bw(16)
set.seed(1234) df <- tibble(grp = LETTERS[1:10], value = rnorm(n=10, mean=20, sd=40))|> mutate(direction=ifelse(value>0, "up", "down")) df # A tibble: 10 × 3 grp value direction <chr> <dbl> <chr> 1 A -28.3 down 2 B 31.1 up 3 C 63.4 up 4 D -73.8 down 5 E 37.2 up 6 F 40.2 up 7 G -2.99 down 8 H -1.87 down 9 I -2.58 down 10 J -15.6 down
How to annotate barplots with both positive and negative bars
df |> ggplot(aes(x=grp, y=value, fill=direction))+ geom_col()+ theme(legend.position="none") ggsave("barplot_with_both_negative_n_positive_bars.png")
Annotating barplots with both positive and negative bars using geom_text()
df |> ggplot(aes(x=grp, y=value, fill=direction))+ geom_col()+ theme(legend.position="none")+ geom_text(aes(label=round(value))) ggsave("annotate_barplot_with_geom_text.png")
Adjusting annotation location on barplot using geom_text()’s nudge_x or nudge_y is hard
df |> ggplot(aes(x=grp, y=value, fill=direction))+ geom_col()+ theme(legend.position="none")+ geom_text(aes(label=round(value)), nudge_y=5) ggsave("annotate_barplot_with_geom_text_with_nudge_to_align.png")
Correctly align annotation on barplot with both negative and positive values on bars
df |> ggplot(aes(x=grp, y=value, fill=direction))+ geom_col()+ theme(legend.position="none")+ geom_text(aes(y= value + 5*sign(value) , label=round(value))) ggsave("annotate_barplot_with_both_negative_n_positive_values_on_bars_aligned.png")
Correctly align annotation on a horizontal barplot with both negative and positive values
df |> ggplot(aes(y = grp, x=value, fill=direction))+ geom_col()+ theme(legend.position="none")+ geom_text(aes(x = value + 5*sign(value), label=round(value))) ggsave("annotate_horizontal_barplot_with_both_negative_n_positive_values_on_bars_aligned.png")