different colors for each bar in stacked bar graph - base graphics
Asked Answered
J

3

15

I want to plot a stacked bar graph like the one attached, but I want the colors to vary between the categories aa, bb and cc. Specifically, I want the grey blocks in bb to be red and the grey blocks in cc to be green. The following code serves as a simple example and illustrates what I have already tried:

aa=c(0.2,0.6,0.1,0.1)
bb=c(0.4,0.5,0.05,0.05)
cc=c(0.5,0.25,0.1,0.15)
x=cbind(aa,bb,cc)
x #the data
aa   bb   cc

[1,] 0.2 0.40 0.50
[2,] 0.6 0.50 0.25
[3,] 0.1 0.05 0.10
[4,] 0.1 0.05 0.15

default behavior, all blocks have the same color in each categories

col=rep(c("white","grey"),2)
col
# [1] "white" "grey"  "white" "grey" 

barplot(x,col=col)

but I want the grey blocks in bb to be red and the grey blocks in cc to be green

col=cbind(rep(c("white","grey"),2),rep(c("white","red"),2),rep(c("white","green"),2))
col

[,1]    [,2]    [,3]   
[1,] "white" "white" "white"
[2,] "grey"  "red"   "green"
[3,] "white" "white" "white"
[4,] "grey"  "red"   "green"

barplot(x,col=col) #not working

col=c(rep(c("white","grey"),2),rep(c("white","red"),2),rep(c("white","green"),2))
col
[1] "white" "grey"  "white" "grey"  "white" "red"   "white" "red"   "white" "green" "white" "green"

barplot(x,col=col) #not working either

Many thanks for any suggestions.

example graph

Jamboree answered 1/4, 2014 at 9:25 Comment(2)
barp() in the plotrix package allows feeding a matrix to col - but it only does grouped barplots, not stacked ones. You may need to roll your own function here (probably with lots of calls to rect()). If you do, please do post it here, I'll happily upvote it.Feaster
That solution was addressed here: stat.ethz.ch/pipermail/r-help/2007-March/126848.html . But the solutions below are more straightforward for me because I need only one color per bar.Jamboree
D
8

A workaround: extend your matrix so that values correspond to fictitious categories, with just one color per category. Only one of aa, bb and cc will actually have data in those categories.

xx <- rep(0,4)
x <- matrix(c(aa,xx,xx,xx,bb,xx,xx,xx,cc),ncol=3)
x
      [,1] [,2] [,3]
 [1,]  0.2 0.00 0.00
 [2,]  0.6 0.00 0.00
 [3,]  0.1 0.00 0.00
 [4,]  0.1 0.00 0.00
 [5,]  0.0 0.40 0.00
 [6,]  0.0 0.50 0.00
 [7,]  0.0 0.05 0.00
 [8,]  0.0 0.05 0.00
 [9,]  0.0 0.00 0.50
[10,]  0.0 0.00 0.25
[11,]  0.0 0.00 0.10
[12,]  0.0 0.00 0.15

And plot as you did:

col <- c(rep(c("white","grey"),2),rep(c("white","red"),2),rep(c("white","green"),2))
barplot(x,col=col)

enter image description here

Deoxidize answered 1/4, 2014 at 9:50 Comment(0)
A
8

This works by adding one coloured bar to the plot at a time:

# white bars 
barplot(x, col='white', axes=F, axisnames=F, yaxp=c(0,1,2), las=1)
cols=c('grey','red','green')

# add coloured bars
for (i in 1:ncol(x)){
    xx = x
    xx[,-i] <- NA
    colnames(xx)[-i] <- NA
    barplot(xx,col=c('white',cols[i]), add=T, axes=F) 
}

stacked plot

Aluminate answered 1/4, 2014 at 9:56 Comment(0)
S
5
library(ggplot2)
library(reshape2)
x <- data.frame(aa=c(0.2,0.6,0.1,0.1),
                bb=c(0.4,0.5,0.05,0.05),
                cc=c(0.5,0.25,0.1,0.15),
                dd = 1:4)
x <- melt(x, "dd")
col=c(rep(c("white","grey"),2),rep(c("white","red"),2),rep(c("white","green"),2))
ggplot(x, aes(x = variable, y = value)) + geom_bar(stat = "identity", fill = col)

enter image description here

Stanzel answered 1/4, 2014 at 9:49 Comment(2)
This is a very neat solution with just one vector of colours and simply fill = col. Can this approach work for any ggplot? (I wonder how did you know the order in which the plot would use the colours?)Simas
This is very old and I would think there should be a better way to build the col vector. Regarding ggplot, yes, it was designed to work with long (or tidy) format, hence it will always "prefer" one column. Hadely designed it by this theory vita.had.co.nz/papers/tidy-data.pdfStanzel

© 2022 - 2024 — McMap. All rights reserved.