Search code examples
rggplot2bar-chartgeom-text

ggplot2: Add two number of observation in each stacked graph


I have a df as it follows:

fruit <- data.frame(Sample=1:100, 
        Fruit=c(rep("Apple", 10), rep("Strawberry", 25), rep("Grape", 20), 
              rep("Watermelon", 15), rep("Lime", 11), rep("Blueberry", 10), 
              rep("Plum", 9)), 
        Color=c(rep("Red", 30), rep("Green", 45), 
                rep("Blue", 25)), 
        Ripe=c(rep(c(T, F), 50)))+

fruit$Fruit <- factor(fruit$Fruit, unique(fruit$Fruit))+
fruit$Color <- factor(fruit$Color, unique(fruit$Color))

Then, I've plotted the bar graph:

foo <- aggregate(Sample ~ Color, data = fruit, FUN = length)

library(ggplot2)
ggplot(fruit, aes(Color, fill = Color, alpha = Ripe)) +
geom_bar(color = "black") +
geom_text(data = foo, aes(label = Sample, y = Sample), alpha = "1", vjust = -1)
scale_alpha_discrete(range = c(1, 0.6)) +
theme(axis.title.x = element_blank(), 
      axis.text.x = element_blank(), 
      axis.ticks.x = element_blank()) +
guides(fill = guide_legend(override.aes = list(colour = NA)))

With the command above I was able to create the following bar-graph:

enter image description here

So...I was able to put the total number of observations for each Color above each bar...but I'm wonder how can I put the total n of observation for TRUE in each color bar. In this case would be two n observation for each bar, with one above the bar as the total n of each Color (as you can already see), and above the TRUE bar the TRUE n observation for that particular Color...


Solution

  • You could add a little more aggregation:

    foo2 <- aggregate(Ripe ~ Color, data = fruit, FUN = sum)
    
    foo2$label <- foo2$Ripe
    foo$label <- foo$Sample
    foo_stack <- do.call(rbind, list(foo[,c("Color", "label")], foo2[,c("Color","label")]))
    

    And then change your geom_text() to:

    geom_text(data = foo_stack, aes(label = label, y = label), alpha = "1", vjust = -1)
    

    Alternatively, you can do all your aggregation in data.table in one step like:

    library(data.table)
    foo_stack <- as.data.table(fruit)    
    foo_stack[,.(labels = c(sum(Ripe == TRUE), length(Ripe))) , by = Color]  
    

    enter image description here