0

This question is related to : Grouped, Stacked Barplot Over Time

How can this kind of barplot (stacked by one variable and dodged by another) possible in ggplot. I tried following but it did not work:

data1  = cbind(c(1,1.25),c(1.2,1.5),c(.75,1.2))
data2  = cbind(c(1.3,1.5),c(1,1.25),c(1.25,.75))    
> data1
     [,1] [,2] [,3]
[1,] 1.00  1.2 0.75
[2,] 1.25  1.5 1.20
> data2
     [,1] [,2] [,3]
[1,]  1.3 1.00 1.25
[2,]  1.5 1.25 0.75
> 
> 
> dd1 = data.frame(data1)
> dd1$id = 'first'

> dd2 = data.frame(data2)
> dd2$id = 'second'

> 
> dd = rbind(dd1, dd2)
> dd
    X1   X2   X3     id
1 1.00 1.20 0.75  first
2 1.25 1.50 1.20  first
3 1.30 1.00 1.25 second
4 1.50 1.25 0.75 second
> 

> dd$row = c(1,2,1,2)
> melt(dd, id=c('id','row'))
       id row variable value
1   first   1       X1  1.00
2   first   2       X1  1.25
3  second   1       X1  1.30
4  second   2       X1  1.50
5   first   1       X2  1.20
6   first   2       X2  1.50
7  second   1       X2  1.00
8  second   2       X2  1.25
9   first   1       X3  0.75
10  first   2       X3  1.20
11 second   1       X3  1.25
12 second   2       X3  0.75
> 

> 
ggplot(mm)+
    geom_bar(data=mm[mm$id=='first',], aes(x=variable, y=value, fill=factor(row)),stat='identity')+
    geom_bar(data=mm[mm$id=='second',], aes(x=variable, y=value, fill=factor(row)),stat='identity')

But it creates only a single stacked bar rather than 2 stacked bars.

I wish future version of ggplot has stack=varA, dodge=varB options rather than fill=var1, so that one or both can be applied easily.

Community
  • 1
  • 1
rnso
  • 23,686
  • 25
  • 112
  • 234
  • 1
    I think you can't have both but [here](http://stackoverflow.com/questions/12715635/ggplot2-bar-plot-with-both-stack-and-dodge) are some alternatives – Didzis Elferts Sep 06 '14 at 08:23

2 Answers2

1

If I understand what you're trying to do, for plotting purposes you could try modifying the values of "variable" in the "second" data set such that the ggplot sees them as different but they appear the same on the plot. Your plotting code would then look like:

 mm$variable <- factor(mm$variable, c(levels(mm$variable), paste(levels(mm$variable)," ")), ordered=TRUE)
 mm$variable[mm$id=="second"] <- paste(mm$variable[mm$id=="second"]," ")
 ggplot(mm)+ 
 geom_bar(data=mm, aes(x=variable, y=value, fill=factor(row), colour=id), stat='identity', size= 1.5) +
 scale_colour_manual( values=c(first="black", second="red"))

Just for the example, I've used the color of the border around the bars to distinguish the first set from the second but you could do something else.

Update - Actually that easier. You'll need to include the grid library to set the panel separation.

library(grid)
ggplot(mm)+
geom_bar(data=mm, aes(x=id, y=value, fill=factor(row)), stat='identity', size= 1.3, width=.5) +
theme(panel.margin.x= unit(0,"cm")) +
facet_wrap(~ variable, scales = "free_x")

enter image description here

WaltS
  • 5,410
  • 2
  • 18
  • 24
  • It is close to what I want but "X1" and "X1 " need to be next to each other (same for "X2" etc). Also it will be perfect if there is some extra space between "X1","X1 " and "X2","X2 ". – rnso Sep 06 '14 at 13:03
0

maybe this

Layered axes in ggplot?

will give you an idea how to solve your task.

In my solution your stack = varA corresponds to my xaxis.inner and your dodge = varB corresponds to my xaxis.outer

Hope this helps

Tom

Community
  • 1
  • 1
Tom Martens
  • 746
  • 9
  • 18
  • Very helpful link with a number of solutions. Your solution achieves what is needed even though it is long. Facet_wrap is the simplest to use. – rnso Sep 07 '14 at 01:36