rggplot2bar-chart

Fix order of stacks but allow colour to change


The data and code for this question were adapted from:

How to fill colors of stacked bar plot depending on colors column of df in R using ggplot

I want to fix the order of country appearance in each stack so that "USA" is on the bottom and "Other" is at the top, but allow the colours associated with each country in each stack to change. The attempted code:

library(tidyverse)
producer_countries <- tribble(~Country,    ~year,   ~total_value,  ~col,    
                        "USA",      1995,   100,        "green",
                        "China",    1995,   177,        "red",
                        "Other",    1995,   150,        "brown",
                        "USA",      2000,   100,        "red",
                        "China",    2000,   177,        "green",
                        "Other",    2000,   320,        "brown")

ggplot(producer_countries, aes(fill=Country, y=total_value, x=year)) +     
  geom_bar(position="stack", stat="identity",  color = "black", aes(fill=col))+
  scale_fill_identity() +
  xlab("Year") +
  ylab("Quantity")

produces

Stacked bar chart with custom colours

But the ordering is by colour, i.e. red is always on the bottom, whereas I need the order to be green, red, brown in the left bar, and red, green, brown in the right bar.


Solution

  • ggplot by default sorts alphabetically. You can override that behaviour by making the variable mapped t the y axis a factor, with

    producer_countries$Country <- factor(producer_countries$Country, levels = c("Other", "China", "USA"))
    

    TBH, assigning different coloUrs to the same country, without any other means of distinguishing them would make your chart very difficult to understand. I'd so something like:

    library(tidyverse)
    producer_countries <- tribble(~Country,    ~year,   ~total_value,  ~col,    
      "USA",      1995,   100,        "green",
      "China",    1995,   177,        "red",
      "Other",    1995,   150,        "brown",
      "USA",      2000,   100,        "red",
      "China",    2000,   177,        "green",
      "Other",    2000,   320,        "brown")
    
    producer_countries$Country <- factor(producer_countries$Country, levels = c("Other", "China", "USA"))
    
    ggplot(
      producer_countries, 
      aes(
        #fill=col, 
        fill=Country,
        y=total_value, x=year)
      ) +     
      geom_bar(
        position="stack", 
        stat="identity",  
        color = "black", 
        )+
      geom_text(
        aes(label=Country), 
        position=position_stack(vjust=0.5)
        ) +
      # scale_fill_identity()+
      scale_fill_manual(values = c("China" = "red", "USA" = "green", "Other" = "brown")) +
      xlab("Year") +
      ylab("Quantity")