Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ggplot dodged bar chart using stat="identity"?

Tags:

r

ggplot2

I have a data frame with two columns, A and B. I want to produce a bar plot with values in A and B plotted side by side (dodged). I googled around and found ggplot from package ggplot2. The default is to generate a bar chart using frequencies, but there is an option stat="identity" that allows to pick a variable to set bar heights explicitly. I can plot one column like so:

d <- data.frame(A=c(1:10), B=c(11:20))
ggplot(data=d, aes(x=1:length(A), y=A))+geom_bar(stat="identity", position="dodge")

How do I plot two columns side by side? I can structure my data frame differently: append values from vectors A and B into one column and create an indicator variable ind, then use it to define groups aes(group=ind). Can this be done with data frame d as-is, without modifying its structure?

like image 576
user443854 Avatar asked Jan 29 '13 16:01

user443854


2 Answers

You can use melt from the reshape2 package to create plot like you're looking for.

library(reshape2)
d$ind <- seq_along(d$A)

d.m <- melt(d, id.var='ind')

ggplot(d.m, aes(x=ind, y=value, fill=variable)) + 
  geom_bar(stat='identity', position='dodge')

In general, ggplot works best when you supply all the data in a single data.frame. At least one data.frame per geom type.

like image 102
Justin Avatar answered Sep 23 '22 04:09

Justin


The only good way to do this is to rearrange your data to suit the needs of the 'ggplot' function. However, if you want to do it all in line, you can. You'll just have to reshape the data by hand, like so:

ggplot(data=data.frame(value=c(d$A, d$B), variable=c(rep("A",10),rep("B",10))), aes(x=c(1:10,1:10), y=value, fill=variable))+geom_bar(stat="identity", position="dodge")

Here, I have created a new data frame out of the old one and assigned the corresponding variable names (this is what the 'reshape2' package does with the 'melt' function). Then, I have manually assigned the x-values to be 1:10 for "A" and 1:10 for "B" to make the bars appear next to each other, rather than all in order from 1:20. I added a 'fill' argument to change the colors of the bars to represent "A" or "B".

like image 42
Dinre Avatar answered Sep 22 '22 04:09

Dinre