Home > other >  Stacked barplot with continuous labels and breaks in R
Stacked barplot with continuous labels and breaks in R

Time:05-22

Is there a way to make a stacked barplot with continuous breaks and labels? Transforming my dataframe from a "wider version" to a "longer version" allowed me to make a stacked barplot, but now my labels are misaligned (CYR 2009 should be directly above WYR 2010, etc..), which I fixed, but an empty barplot has appeared to the far right above where 2022 was because of this change.

I've tried to only displaying the years <= 2021 and simply shift the 2nd x-axis to the left in order to line-up the two labels, but that doesn't seem to do anything about the "empty" barplot space.

My original data form:

>dput(prop)
structure(list(WYR = c(2010, 2011, 2012, 2013, 2014, 2015, 2016, 
2017, 2018, 2019, 2020, 2021, 2022), CYR = c(2009, 2010, 2011, 
2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021), 
    prop_zero = c(0.745762711864407, 0.888888888888889, 0.739130434782609, 
    0.842857142857143, 0.958333333333333, 0.915492957746479, 
    0.929577464788732, 0.75, 0.76056338028169, 0.720588235294118, 
    0.785714285714286, 0.6875, 0.833333333333333), prop_nonzero = c(0.254237288135593, 
    0.111111111111111, 0.260869565217391, 0.157142857142857, 
    0.0416666666666667, 0.0845070422535211, 0.0704225352112676, 
    0.25, 0.23943661971831, 0.279411764705882, 0.214285714285714, 
    0.3125, 0.166666666666667)), class = "data.frame", row.names = c(NA, 
-13L))

"Longer" version:

    >dput(prop)
    structure(list(WYR = c(2010, 2010, 2011, 2011, 2012, 2012, 2013, 
    2013, 2014, 2014, 2015, 2015, 2016, 2016, 2017, 2017, 2018, 2018, 
    2019, 2019, 2020, 2020, 2021, 2021, 2022, 2022), CYR = c(2009, 
    2009, 2010, 2010, 2011, 2011, 2012, 2012, 2013, 2013, 2014, 2014, 
    2015, 2015, 2016, 2016, 2017, 2017, 2018, 2018, 2019, 2019, 2020, 
    2020, 2021, 2021), class = c("prop_zero", "prop_nonzero", "prop_zero", 
    "prop_nonzero", "prop_zero", "prop_nonzero", "prop_zero", "prop_nonzero", 
    "prop_zero", "prop_nonzero", "prop_zero", "prop_nonzero", "prop_zero", 
    "prop_nonzero", "prop_zero", "prop_nonzero", "prop_zero", "prop_nonzero", 
    "prop_zero", "prop_nonzero", "prop_zero", "prop_nonzero", "prop_zero", 
    "prop_nonzero", "prop_zero", "prop_nonzero"), proportions = c(0.745762711864407, 
    0.254237288135593, 0.888888888888889, 0.111111111111111, 0.739130434782609, 
    0.260869565217391, 0.842857142857143, 0.157142857142857, 0.958333333333333, 
    0.0416666666666667, 0.915492957746479, 0.0845070422535211, 0.929577464788732, 
    0.0704225352112676, 0.75, 0.25, 0.76056338028169, 0.23943661971831, 
    0.720588235294118, 0.279411764705882, 0.785714285714286, 0.214285714285714, 
    0.6875, 0.3125, 0.833333333333333, 0.166666666666667)), row.names = c(NA, 
    -26L), class = c("tbl_df", "tbl", "data.frame"))

Breaks and labels:

   years <- seq(2009,2021,1)
   labs <- seq(2009,2021,by=1)

Plot:

ggplot(prop[which(prop$CYR<=2021),], aes(x=CYR, y=proportions, fill=class))   
  geom_bar(position="fill", stat="identity")   
  scale_y_continuous(limits = c(0, 1.0), expand = expansion(mult = c(0, 0.05)))  
  scale_x_continuous(breaks= years, labels = ~ rep("", length(.x)))  
  # CYR labels
  annotate(geom = "text",
           x = prop$CYR,
           y = -Inf,
           label = labs, 
           size = 8.8 / .pt,
           vjust = 2.5)  
  # WYR labels
  annotate(geom = "text",
           x = prop$WYR,
           y = -Inf,
           label = prop$WYR, 
           size = 8.8 / .pt,
           vjust = 4,
           hjust = 3.4,
           color = "grey")  
  # CYR title
  annotate(geom = "text",
           x = -Inf,
           y = -Inf,
           label = c("CYR"),
           vjust = 2.5, hjust = 1,
           size = 8.8 / .pt)  
  # WYR title
  annotate(geom = "text",
           x = -Inf,
           y = -Inf,
           label = c("WYR"),
           vjust = 4, hjust = 1,
           size = 8.8 / .pt,
           color = "grey")  
  coord_cartesian(clip = "off")  
  theme(axis.title.x = element_blank())   
  # Make extra space between axis ticks and axis title
  theme(axis.text.x.bottom = element_text(margin = margin(t = 8.8, b = 8.8)), 
        axis.text.x = element_text(size = 10, color = "grey"),
        axis.title.x = element_blank(),
        axis.text.y = element_text(size = 10),
        axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0), size = 14),
        axis.ticks = element_line(colour = "black", size = 1), 
        panel.border = element_rect(fill = NA, color = "black", size = 1), 
        legend.position = "none")  
  labs(y = "Proportion")

CodePudding user response:

The issue is that you use x = prop$WYR as the x coordinates for your WYR labels which adds an empty bar for year 2022. Instead use x = prop$CYR and remove the - IMHO - unnecessary hjust to align both rows of labels.

library(ggplot2)

years <- seq(2009, 2021)

ggplot(prop[which(prop$CYR <= 2021), ], aes(x = CYR, y = proportions, fill = class))  
  geom_bar(position = "fill", stat = "identity")  
  scale_y_continuous(limits = c(0, 1.0), expand = expansion(mult = c(0, 0.05)))  
  scale_x_continuous(breaks = years, labels = ~ rep("", length(.x)))  
  # CYR labels
  annotate(
    geom = "text",
    x = prop$CYR,
    y = -Inf,
    label = prop$CYR,
    size = 8.8 / .pt,
    vjust = 2.5
  )  
  # WYR labels
  annotate(
    geom = "text",
    x = prop$CYR,
    y = -Inf,
    label = prop$WYR,
    size = 8.8 / .pt,
    vjust = 4,
    color = "grey"
  )  
  # CYR title
  annotate(
    geom = "text",
    x = -Inf,
    y = -Inf,
    label = c("CYR"),
    vjust = 2.5, hjust = 1,
    size = 8.8 / .pt
  )  
  # WYR title
  annotate(
    geom = "text",
    x = -Inf,
    y = -Inf,
    label = c("WYR"),
    vjust = 4, hjust = 1,
    size = 8.8 / .pt,
    color = "grey"
  )  
  coord_cartesian(clip = "off")  
  theme(axis.title.x = element_blank())  
  # Make extra space between axis ticks and axis title
  theme(
    axis.text.x.bottom = element_text(margin = margin(t = 8.8, b = 8.8)),
    axis.text.x = element_text(size = 10, color = "grey"),
    axis.title.x = element_blank(),
    axis.text.y = element_text(size = 10),
    axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0), size = 14),
    axis.ticks = element_line(colour = "black", size = 1),
    panel.border = element_rect(fill = NA, color = "black", size = 1),
    legend.position = "none"
  )  
  labs(y = "Proportion")

  • Related