Pepijn95
Pepijn95

Reputation: 321

Add total number to ggplot legend

I made a frequency barplot with the following data and code:

structure(list(Geslacht = c("man", "man", "man", "man", "man", 
"man", "man", "vrouw", "vrouw", "vrouw", "vrouw", "vrouw", "vrouw", 
"vrouw", "vrouw"), Lengteklasse = c(6, 7, 8, 9, 10, 11, 12, 6, 
7, 8, 9, 10, 11, 12, 13), Freq = c(1L, 9L, 19L, 21L, 35L, 22L, 
5L, 2L, 13L, 19L, 37L, 45L, 40L, 6L, 1L)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
    Geslacht = c("man", "vrouw"), .rows = structure(list(1:7, 
        8:15), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -2L), .drop = TRUE))
ggplot(Freq_lengteklasse, aes(Lengteklasse, Freq, fill = Geslacht))+
  geom_col()+
  scale_x_continuous(breaks = seq(6,13, by = 1))+
  scale_y_continuous(breaks = seq(0,80, by = 10))+
  labs(x = "Lengteklasse (cm)", y = "Frequentie")+
  scale_fill_manual(values=c('lightgray','black'))+
  theme_classic()

I want to add the total count of man and vrouw which should say n = 275, positioned under the legend. How would one do this?

Upvotes: 1

Views: 559

Answers (3)

Quinten
Quinten

Reputation: 41573

You can add a tag in your labs which will display the total number. You can change the position of the tag in the theme with plot.tag.position. You can use the following code:

library(tidyverse)
ggplot(Freq_lengteklasse, aes(Lengteklasse, Freq, fill = Geslacht))+
  geom_col()+
  scale_x_continuous(breaks = seq(6,13, by = 1))+
  scale_y_continuous(breaks = seq(0,80, by = 10))+
  labs(x = "Lengteklasse (cm)", y = "Frequentie", tag = paste('n =', sum(Freq_lengteklasse$Freq)))+
  scale_fill_manual(values=c('lightgray','black'))+
  theme_classic() +
  theme(plot.tag.position = c(0.95, 0.4))

Output:

enter image description here

Comment: italic n

You can use substitute and add your value in an env to paste it italic like this:

library(tidyverse)
ggplot(Freq_lengteklasse, aes(Lengteklasse, Freq, fill = Geslacht))+
  geom_col()+
  scale_x_continuous(breaks = seq(6,13, by = 1))+
  scale_y_continuous(breaks = seq(0,80, by = 10))+
  labs(x = "Lengteklasse (cm)", y = "Frequentie", tag = substitute(expr = paste(italic("n"), " = ", x), env = base::list(x = sum(Freq_lengteklasse$Freq))))+
  scale_fill_manual(values=c('lightgray','black'))+
  theme_classic() +
  theme(plot.tag.position = c(0.95, 0.4))

Output:

enter image description here

Upvotes: 1

stefan
stefan

Reputation: 125697

Another option would be to use a cowplot and patchwork hack. Basically this involves to first extract the legend via cowplot::get_legend and creating the annotation as a grob. Afterwards we glue these elements together with the main plot via patchwork.

library(ggplot2)

p <- ggplot(Freq_lengteklasse, aes(Lengteklasse, Freq, fill = Geslacht)) +
  geom_col() +
  scale_x_continuous(breaks = seq(6, 13, by = 1)) +
  scale_y_continuous(breaks = seq(0, 80, by = 10)) +
  labs(x = "Lengteklasse (cm)", y = "Frequentie") +
  scale_fill_manual(values = c("lightgray", "black")) +
  theme_classic()


library(cowplot)
library(patchwork)

legend <- (p + theme(legend.justification = "bottom")) |> get_legend()
annotation <- grid::textGrob(label = "n = 275", y = unit(1, "npc"), vjust = 1)

design = "
AB
AC
"
list(p + guides(fill = "none"), legend, annotation) |> 
  wrap_plots() + 
  plot_layout(widths = c(9, 1), design = design)

Upvotes: 1

Kra.P
Kra.P

Reputation: 15143

annotation_custom will also work for your case.

Freq_lengteklasse %>%
  ggplot(aes(Lengteklasse, Freq, fill = Geslacht))+
  geom_col()+
  scale_x_continuous(breaks = seq(6,13, by = 1))+
  scale_y_continuous(breaks = seq(0,80, by = 10))+
  labs(x = "Lengteklasse (cm)", y = "Frequentie")+
  scale_fill_manual(values=c('lightgray','black'))+
  theme_classic() + 
  annotation_custom(grob = textGrob("n = 275"),  
                    xmin = 14, xmax = 16, ymin = 26, ymax = 30) +
  coord_cartesian(clip = "off") 

enter image description here

Upvotes: 1

Related Questions