Add sample size to x-axis in ggplot box plots

Hello,

I want to add the number of observations per group in a box plot with the number of observations below the group name in the x-axis, and I want to do this over many plots.

Here is my code to generate the plots (thanks to user help)

target_cols <- colnames(d[15:27])


bx <- function(colname){
  p = ggplot(d) +
    aes(x=as.factor(Depth), y=d[,colname]) +
    geom_boxplot() +
    labs(x="",
         y=colname) +
}

grid.arrange(grobs=map(target_cols, bx))

How can I add the number of observation per group to the x-axis labels?

Here is a snippet of my data:

d <- structure(list(STIS. = c("1000", "1001", "1006", "1007", "1012"
), Month = c("July", "July", "July", "July", "July"), Ship = c("LE2", 
"LE2", "LE2", "LE2", "LE2"), Lake = c("Michigan", "Michigan", 
"Michigan", "Michigan", "Michigan"), Site = c("EAS5", "EAS5", 
"EAS17", "EAS17", "EAS38"), Station = c(NA_character_, NA_character_, 
NA_character_, NA_character_, NA_character_), Research.Project = c("CSMI2021", 
"CSMI2021", "CSMI2021", "CSMI2021", "CSMI2021"), Date = c("7/17/2021", 
"7/17/2021", "7/17/2021", "7/17/2021", "7/16/2021"), Time..EST. = c("15:01 (CDT)", 
"15:01 (CDT)", "10:41 (CDT)", "10:41 (CDT)", "12:42 (CDT)"), 
    Site.Depth..m. = c(49, 49, 186, 186, 246), Integrated.depths..m. = c(NA, 
    NA, NA, NA, NA), Separate.depths..m. = c(5, 25, 5, 35, 5), 
    DCL. = c("N", "N", "Y", "Y", "Y"), Stratified..Unstratified. = c("Stratified", 
    "Stratified", "Stratified", "Stratified", "Stratified"), 
    NH4 = c(19.7, 14.4, 5.93, 10.1, 9.31), NOx = c(347, 338, 
    310, 443, 275), SRP = c(3.51, 3.65, 3.32, 3.92, 3.49), TN = c(509, 
    510, 453, 493, 453), TP = c(9.6, 10.2, 9.77, 9.8, 9.81), 
    K = c(1.36, 1.42, 1.48, 1.35, 1.46), Na = c(7.26, 7.25, 7.25, 
    7.05, 6.85), Ca = c(31.18, 30.69, 30.34, 30.41, 29.31), Mg = c(12.21, 
    12.22, 12.15, 12.21, 11.93), Cl = c(13, 12.97, 13.01, 12.85, 
    12.63), SO4 = c(22.83, 23.18, 23.01, 23, 22.67), Si = c(4.71, 
    5.14, 4.62, 4.92, 4), chl = c(0.63, 0.84, 0.81, 2.34, 1.09
    ), TSS = c(0.507, NA, -0.027, NA, 0.567), VSS = c(0.513, 
    NA, 0.087, NA, 0.56), Depth = c("Epi", "Mid", "Epi", "Mid", 
    "Epi")), row.names = c(NA, 5L), class = "data.frame")

Is this what you had in mind? It ignores NA values.

bx <- function(colname){
  p = d %>%
    select(Depth, {{colname}}) %>%
    mutate(n = ifelse(is.na(.[,2]), 0, 1)) %>%
    group_by(Depth) %>%
    mutate(Depth = paste(Depth, sum(n), sep = '\n')) %>%
    ungroup() %>%
    ggplot() +
    aes(x=as.factor(Depth), y=d[,colname]) +
    geom_boxplot() +
    labs(x="",
         y=colname)
}

That didn't work, unfortunately, not sure why!

I figured it out and am posting the answer here to those who might need it in the future:

target_cols <- colnames(epi[15:27])

bx <- function(colname){
  b <- epi %>%
    select(Ship, {{colname}}) %>%
    na.omit()
  c <- b %>%
    count(Ship)
  myxlab <- paste(as.factor(c$Ship), "\n(N=", c$n, ")", sep="")
  p = ggplot(b) +
    aes(x=as.factor(Ship), y=b[,colname], fill=Ship) +
    geom_boxplot(varwidth = T, alpha=0.2) +
    labs(x=NULL,
         y=colname) +
    theme_bw() +
    theme(legend.position = "none") +
    scale_x_discrete(labels=myxlab)
}

grid.arrange(grobs=map(target_cols, bx), top="Epilimnion")

It looks like Depth in the original bx function was switched to Ship in the final solution. Glad you figured it out!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.