Manually reordering bars in bar chart ggplot2

Hello Everyone,

I am new to R and ggplot2, after a lot of struggle, watching videos and going through various open source sites I have created bar chart for my data.

My data has four columns i.e. Items, Quantity_2001, Quantity_2011 and Change. There are 11 different items with no missing vales. I want to create a side-by-side bar chart where each 'Item' will have three bars: one bar for 2001, one bar for 2011 and one bar for Change. I have managed to create one using the following set of commands:

library(ggplot2)
library(tidyverse)
library(dplyr)

df <- gather(Data, variable, value, -Item)

ggplot(df, aes(Item, value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge", width=0.7)+
labs(y = "Sales") +
theme(axis.text.x = element_text(angle = 90)) +
scale_y_continuous(limits=c(-17, 45), breaks=seq(-17, 45, 10))+
scale_fill_discrete(name="Legend", labels=c("Quantity 2001", "Quantity 2011", "Change"))

So there are three bars for each item, for example 'Item1' has three bars one each for 2001, 2011 and change and so on for all 11 items. However, with the above command, the bars for each item in the chart appear first for 2011, then for 2001 and then change. I want bar for 2001 to appear first, then 2011 and then change. Please let me know if there is a way I can manually reorder the bars.

Thanks,
Raj

You can use the factor function to impose an order on the levels of variable .

library(ggplot2)

DF <- data.frame(Item = rep(LETTERS[1:11],3), 
                 variable = rep(c("a", "b", "c"), each = 11),
                 value = sample(1:33))
DF$variable = factor(DF$variable, levels = c("c", "a", "b"), ordered = TRUE)
ggplot(DF, aes(x = Item, y = value, fill = variable)) +
  geom_bar(stat = "identity", position = "dodge", width=0.7, orientation = "x")+
  labs(y = "Sales") +
  theme(axis.text.x = element_text(angle = 90))

Created on 2020-06-08 by the reprex package (v0.3.0)

1 Like

I used the letters only as a convenience since I do not know how your Items are named. You should be able to use my code with your data frame except in the factor() function the levels should be

levels = c("Quantity 2001", "Quantity 2011", "Change")

You are a genius, this worked, thank you very very much.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

Thank you very much, this worked. One more question, is there a way to change the names of items on x-axis from 'A', 'B', 'C', to the proper names of item in my data and changing color of the bars.

Thanks,
Raj

Thank you again. My items include agri commodities like rice, maize etc. When I use rep(LETTERS[1:14] the chart I get is correct. However, when I try to replace the LETTERS A, B, C using the following code I get an error which says Error in LETTERS["Maize", "Rice_paddy", "Beans_dry", "Seed_cotton", "Cassava", incorrect number of dimensions

DF <- data.frame(Item = rep(LETTERS["Maize", "Rice_paddy", "Beans_dry",
"Seed_cotton", "Cassava", "Sugarcane", "Wheat", "Cocoa_beans", "Groundnuts",
"Vegetables_fresh", "Soybeans", "],3),
variable = rep(c("Quantity_in_1961", "Quantity_in_2013", "Change"), each = 11), value = sample(1:33))

I was wondering if you can find the mistake which I am doing.

Thanks,
Raj

Because you are new to R and the Tidyverse I'm going to recommend R for Data Science. It has helped me get a better understanding of the basics and helped me narrow down my internet search queries for the times when I need to find an example of what I'm trying to accomplish. Find the book here:

1 Like

I see I confused you with my code. The following part of my code is just me inventing some data to work with.

With your data you would do something like this.

df <- gather(Data, variable, value, -Item)
df$variable <- factor(df$variable, levels = c("Quantity 2001", "Quantity 2011", "Change"))

ggplot(df, aes(Item, value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge", width=0.7)+
labs(y = "Sales") +
theme(axis.text.x = element_text(angle = 90)) +
scale_y_continuous(limits=c(-17, 45), breaks=seq(-17, 45, 10))+
scale_fill_discrete(name="Legend")
1 Like

Thank you very much, the book will be helpful.