Labeling bar charts with ggplot2
Prerequisites
You need to have the tidyverse
package installed and loaded to run the code in this post.
Here is the theme we use for the plots
custom_theme <- ggplot2::theme_minimal() %+replace%
ggplot2::theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank(),
legend.position = "none",
text = element_text(size = 16)
)
ggplot2::theme_set(custom_theme)
Suppose we want to create a bar chart with labels on top of the bars. This can be achieved using the geom_text
function.
However, the labels are not aligned with the bars. To fix this we need to adjust the labels using the vjust
argument.
The correct adjustment is vjust = -0.5
. Now the resulting bar chart looks great!
This works fine, if all the values are positive. But what if we have negative values?
To test what happens, we will use a fictional dataset that contains the net profit of some company for different years.
company_data <- tibble::tibble(
year = c(2015, 2016, 2017, 2018, 2019),
return = c(-3.2, -1.5, 2.3, -0.1, 1.2)
)
Now we plot the net profit
ggplot(
company_data,
aes(
x = year,
y = return,
fill = return > 0
)
) +
geom_bar(stat = "identity") +
geom_text(
aes(
label = return
),
vjust = -0.5
) +
scale_fill_manual(
values = c("#9b2113", "#024e73"),
guide = FALSE
) +
labs(
title = "Net profit for each year",
subtitle = "In millions of dollars",
x = "Year"
)
As we can see, the labels are not aligned with the bars 😥. This is because we just raise each label, but we actually want to lower the label if the value is negative.
How to fix it
To fix this plot we need to adjust the vjust
argument depending on the value.
This can be done using ifelse(return > 0, -0.5, adjustment_for_negative_values)
.
The correct adjustment is not 0.5
, as one would assume but 1.5
.
To access the value of return
, we also need to put the vjust
argument inside the aes
function.
Putting everything together we get the following code
ggplot(
company_data,
aes(
x = year,
y = return,
fill = return > 0
)
) +
geom_bar(stat = "identity") +
geom_text(
aes(
label = return,
vjust = ifelse(
return > 0, -0.5, 1.5
)
),
size = 5
) +
scale_fill_manual(
values = c("#9b2113", "#024e73"),
guide = FALSE
) +
labs(
title = "Net profit for each year",
subtitle = "In millions of dollars",
x = "Year"
)