rnso
rnso

Reputation: 24535

Stacked+dodged/beside barplot in ggplot

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.

Upvotes: 0

Views: 1155

Answers (2)

WaltS
WaltS

Reputation: 5530

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

Upvotes: 1

Tom Martens
Tom Martens

Reputation: 776

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

Upvotes: 0

Related Questions