Home > Net >  Labels in a grouped bar chart with multiple groups
Labels in a grouped bar chart with multiple groups

Time:09-21

I want to show labels in a grouped bar chart. There are a number of answers to this question in stackoverflow which I have tried, but none of them work in my application.

My chart shows a group of bars for two quarters, 2020 Q4 and 2021 Q1. The labels do not appear on top of the bars as they should. I find that when I change the chart to show bars for 2020 Q4 only, or 2021 Q1 only, then the labels appear properly, but when I show both quarters together, for comparison purposes, the labels no longer appear where they should. Here is my reprex. Help appreciated.

Date <- as.Date(c("2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01"))
GEO <- c(
"Canada","Newfoundland and Labrador","Prince Edward Island",     
"Nova Scotia","New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan",             
"Alberta","British Columbia","Yukon","Northwest Territories","Nunavut",
"Canada","Newfoundland and Labrador","Prince Edward Island","Nova Scotia",              
"New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan","Alberta",                  
"British Columbia","Yukon","Northwest Territories","Nunavut")
JVR <- c(3.5,2.6,3.2,3.3,3.9,4.1,3.4,3.1,2.3,2.4,4.2,4.4,3.0,2.6,
  3.6,2.0,2.5,3.2,3.2,4.2,3.3,3.1,2.7,2.8,4.5,4.7,4.2,3.6)
df <- data.frame(Date=as.Date(Date),GEO=GEO,JVR=JVR)
ggplot(filter(df,Date>=as.Date("2020-10-01")),aes(x=Date,y=JVR,fill=GEO))  
  geom_bar(stat="identity",position="dodge")  
  geom_text(aes(label=JVR,group=GEO),position=position_dodge(width=0.9),
    vjust=-1,size=3)

CodePudding user response:

The ggfittext package can help here. If you'd like to have equal text sizes for the labels, you'd probably need to convert them using format, otherwise e.g. the number "3" will appear larger than "3.1" to fit in the bar.

get data

library(tidyverse)

Date <- as.Date(c("2020-10-01","2020-10-01","2020-10-01","2020-10-01",
                  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
                  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
                  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
                  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
                  "2021-01-01","2021-01-01","2021-01-01","2021-01-01"))
GEO <- c(
  "Canada","Newfoundland and Labrador","Prince Edward Island",     
  "Nova Scotia","New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan",             
  "Alberta","British Columbia","Yukon","Northwest Territories","Nunavut",
  "Canada","Newfoundland and Labrador","Prince Edward Island","Nova Scotia",              
  "New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan","Alberta",                  
  "British Columbia","Yukon","Northwest Territories","Nunavut")
JVR <- c(3.5,2.6,3.2,3.3,3.9,4.1,3.4,3.1,2.3,2.4,4.2,4.4,3.0,2.6,
         3.6,2.0,2.5,3.2,3.2,4.2,3.3,3.1,2.7,2.8,4.5,4.7,4.2,3.6)
df <- data.frame(Date=as.Date(Date),GEO=GEO,JVR=JVR)

plot data

library(ggplot2)
library(ggfittext)
d.plot <- filter(df,Date>=as.Date("2020-10-01"))

ggplot(d.plot, aes(x=Date,y=JVR,fill=GEO,label=format(JVR, digits = 2)))  
  geom_bar(stat="identity",position="dodge")  
  # from `ggfittext`
  geom_bar_text(position="dodge",
                place="top",grow=F,reflow=F,min.size=0)  
  theme_bw()

Created on 2021-09-20 by the reprex package (v2.0.1)

CodePudding user response:

I think the issue is with the continuous Date variable on the x-axis. In your example with x=Date, the position_dodge(width= 0.9) parameter does not work.

But if you convert the two dates of interest into factors (e.g. 2020 Q4 and 2021 Q1) the width = 0.9 parameter works. In this example I think this gives a more meaningful x-axis, so you don't confuse the dodged bars for different dates.

Note geom_col is equivalent to geom_bar(stat = 'identity').

# does not work
ggplot(df, aes(x=Date, y=JVR, fill=GEO))  
  geom_col(position = 'dodge')  
  geom_text(aes(label=JVR), position = position_dodge(width = .9))

# works

df %>%
  mutate(quarter = case_when(
    Date == "2020-10-01" ~ '2020 Q4',
    Date == "2021-01-01" ~ '2021 Q1')) %>%
  ggplot(aes(x=quarter, y=JVR, fill=GEO))  
  geom_col(position = 'dodge')  
  geom_text(aes(label=JVR), position = position_dodge(width = .9))

Created on 2021-09-20 by the reprex package (v2.0.0)


Data

library(tidyverse)

Date <- as.Date(c("2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2020-10-01","2020-10-01","2020-10-01","2020-10-01","2020-10-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01","2021-01-01",
  "2021-01-01","2021-01-01","2021-01-01","2021-01-01"))
GEO <- c(
"Canada","Newfoundland and Labrador","Prince Edward Island",     
"Nova Scotia","New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan",             
"Alberta","British Columbia","Yukon","Northwest Territories","Nunavut",
"Canada","Newfoundland and Labrador","Prince Edward Island","Nova Scotia",              
"New Brunswick","Quebec","Ontario","Manitoba","Saskatchewan","Alberta",                  
"British Columbia","Yukon","Northwest Territories","Nunavut")
JVR <- c(3.5,2.6,3.2,3.3,3.9,4.1,3.4,3.1,2.3,2.4,4.2,4.4,3.0,2.6,
  3.6,2.0,2.5,3.2,3.2,4.2,3.3,3.1,2.7,2.8,4.5,4.7,4.2,3.6)
df <- data.frame(Date=as.Date(Date),GEO=GEO,JVR=JVR)
  • Related