Search code examples
rgeom-bar

Add text with number of observations on facet diverging bar chart


I would like to show the text of the number of observations as shown on the bar chart for the range values that are above and below the mean.

I tried the following

using the Electric Vehicles dataset

light data wrangling to remove spaces and -

https://www.kaggle.com/datasets/mohamedalishiha/electric-vehicles?select=evdataset.csv

EV <- read_csv("evdataset.csv")


 EV$range_norm <- round((EV$ElectricRange - mean(EV$ElectricRange))/
                          sd(EV$ElectricRange),2)

 EV$range_type <- ifelse(EV$range_norm > 0, "above", "below") 

 EV <- EV[order(EV$range_norm), ] 

 EV$Make <- factor(EV$Make, levels = EV$Make) 
ggplot(EV, aes(x = reorder(Make,range_norm), y = range_norm,
               label = range_norm)) +
  geom_bar(stat = 'identity',aes(fill = range_type)) +
  geom_text() +
  facet_wrap(vars(as.factor(Drive))) +
  coord_flip()

I was expecting something like this but for the number of observations of each bar..

enter image description here


Solution

  • Are you looking for something like this?

    library(tidyverse)
    EV <- read_csv("evdataset.csv")
    EV$range_norm <- (EV$`Electric Range` - mean(EV$`Electric Range`))/sd(EV$`Electric Range`)
    
    EV$range_type <- ifelse(EV$range_norm > 0, "above", "below") 
    
    plot_data <- EV |> group_by(Make, Drive, range_type) |> 
      summarize(count = n()) |> 
      mutate(count = ifelse(range_type == "above", count, -count)) |> 
      ungroup()
    
    plot_order <- plot_data |> 
      group_by(Make) |> 
      summarize(totalcount = sum(count)) |> 
      arrange(totalcount) |> 
      pull(Make)
    
    ggplot(plot_data, aes(x = fct_relevel(Make, plot_order),
                          y = count,
                          fill = range_type,
                          label = count)) +
      geom_col() +
      geom_text(size = 3) +
      facet_wrap(~Drive) +
      coord_flip() +
      xlab("Make")
    

    enter image description here