Home > Software engineering >  Adding data labels for totals as well as class-specific values in a stacked column chart
Adding data labels for totals as well as class-specific values in a stacked column chart

Time:05-19

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:

Original graph from Excel

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) 


Graph generated in R

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

enter image description here

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
  )
  • Related