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

11,305

Solution 1

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.

Solution 2

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".

Share:
11,305
user443854
Author by

user443854

Updated on June 07, 2022

Comments

  • user443854
    user443854 almost 2 years

    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?

  • user443854
    user443854 about 11 years
    This means changing the original data frame. I was wondering if there is a parameter/option that can be given to ggplot to use values from multiple columns. I will wait a bit before accepting your answer. Thanks.
  • Justin
    Justin about 11 years
    There are ways, but they aren't pretty. As I mentioned in my edit, ggplot generally works best if you can get your data into a format similar to the one above before plotting. If you don't want to alter your data.frame in the global environment, you can do so in a function instead. Just remember to wrap your ggplot call in print if you do!
  • Dinre
    Dinre about 11 years
    @Justin is correct. You should change how the data is inputted into the 'ggplot' function. The 'ggplot' function is (in)famous for not reshaping your data, so it's best to reshape manually to suit your needs first. I've added an answer that shows how you could do this in-line, but Justin's use of 'melt' is the recommended approach. The 'reshape' package is one of the staples that almost everyone should learn.
  • Matt Bannert
    Matt Bannert about 10 years
    great, simply didn't know I could use identity and dodge at the same time. cool.