Main question
When creating a stacked column chart using R's ggplot2
library, how can I add data labels for the column totals as well as data labels for each individual class/value?
Context
I'm trying to replicate the following graph (originally created in Excel) using R's ggplot2
library:
Figure 1 - Graph Generated in Excel
Reproducible example & data
Here is a reproducible example of my data and the code I'm using:
# Loading libraries
library(ggplot2)
library(extrafont)
# Creating the data.frame object
data = data.frame(year=c(2017,2017,2017,2017,
2018,2018,2018,2018,
2019,2019,2019,2019,
2020,2020,2020,2020,
2021,2021,2021,2021),
hsys=factor(c('Interstate Highways', 'US Highways', 'State Highways', 'FM Roads',
'Interstate Highways', 'US Highways', 'State Highways', 'FM Roads',
'Interstate Highways', 'US Highways', 'State Highways', 'FM Roads',
'Interstate Highways', 'US Highways', 'State Highways', 'FM Roads',
'Interstate Highways', 'US Highways', 'State Highways', 'FM Roads'),
levels = c('Interstate Highways',
'US Highways',
'State Highways',
'FM Roads')),
num_crashes=c(3845,3562,3436,5749,
3978,3502,3565,5836,
4510,3692,3618,6133,
3517,2945,2957,4978,
4698,3765,3645,6158))
p = ggplot(data,
aes(fill=hsys,
y=num_crashes,
x=year,
label=format(num_crashes,
big.mark = ",",
decimal.mark = ".",
scientific = FALSE),
))
geom_bar(position="stack",
stat="identity")
geom_text(size=3,
position = position_stack(vjust=0.5,),
color='white',
family = "Franklin Gothic Book",
fontface = 'bold')
theme(plot.title = element_text(family="Franklin Gothic Demi Cond",
hjust = 0.5),
axis.title = element_text(family = "Franklin Gothic Book",),
axis.text = element_text(family = "Franklin Gothic Book",),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
axis.title.x=element_blank(),
axis.ticks.x=element_blank(),
legend.position = "bottom",
legend.text = element_text(family = "Franklin Gothic Book",),
legend.title = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
)
scale_fill_manual(values = c("#3869A2",
"#0F3859",
"#CC7B28",
"#F4BC46",
"#79A03F"))
ggsave('hsys.jpg', p)
Figure 2 - Graph Generated in R
You'll notice that, aside from the image dimensions and font sizes not matching, they both contain almost the exact same content. The thing that's really missing are the data labels for the column totals at the top of each column.
My attempt
A second approach to achieve your desired result would be to use stat_summary
to compute the totals on the fly like so:
p
stat_summary(
geom = "text", aes(group = 1, label = format(..y..,
big.mark = ",",
decimal.mark = ".",
scientific = FALSE
), ), fun = "sum", color = "black",
family = "Franklin Gothic Book",
fontface = "bold", vjust = -0.5
)