Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map ggplot histogram x-axis intervals to fixed colour palette?

I am trying to stratify my ggplot2 histogram into fixed intervals and colour them based on a specific colour palette: 'x<4':black; '4<x<6':blue; '6<x<8':yellow; and so on...

I tried 2 ways, both of which didn't work.

Referring to my code below, alternative 1 fails when NoOfElement falls to a small figure, say, 500, and there is no element in the first interval 'x<4'. ggplot2 then assigns 'black' to whichever is the first interval (this would be '4<x<6' when size=500). But this is not what I want (see picture).

enter image description here

In Alternative 2, I created another variable in my data frame and assigned the colours for each element. I did this based on a modification of the solution given in: Set specific fill colors in ggplot2 by sign. Unfortunately, the resulting histogram has colours randomly assigned by ggplot2.

I'm quite stuck and would really appreciate some help. Thanks in advance!

Sample code:

library(ggplot2)

NoOfElement <- 5000; MyBreaks <- c(-Inf, seq(4, 16, by=2), Inf)
MyColours <- c("black", "blue", "yellow", "green", "gray", "brown", "purple", "red")

set.seed(2)
c <- data.frame(a=rnorm(NoOfElement, 10, 2), b=rep(NA, NoOfElement))
c$b <- cut(c$a, MyBreaks)

try <- 1  # Allows toggling of alternatives below
if (try==1)
{
  p <- ggplot( c, aes(x=c$a, fill=c$b) ) + geom_histogram( binwidth=0.2 ) + 
    scale_fill_manual(breaks = levels(c$b), values = MyColours, 
                      name = "X Intervals") + 
    scale_x_continuous( limits=c(2, 20))
}else
{
  c$BarCol <- factor(c$b, levels = levels(c$b), labels = MyColours)

  p <- ggplot( c, aes(x=c$a, fill=c$b) ) + geom_histogram( binwidth=0.2 ) + 
    scale_fill_manual(values = c$BarCol, name = "X Intervals") + 
    scale_x_continuous( limits=c(2, 20))
}
plot (p)
like image 331
NoviceProg Avatar asked Jan 22 '14 12:01

NoviceProg


1 Answers

There's a drop argument in scale_ family for empty levels:

NoOfElement <- 500; MyBreaks <- c(-Inf, seq(4, 16, by=2), Inf) 
MyColours <- c("black", "blue", "yellow", "green", "gray", "brown", "purple", "red")

set.seed(2) 
c <- data.frame(a=rnorm(NoOfElement, 10, 2), b=rep(NA, NoOfElement)) 
c$b <- cut(c$a, MyBreaks)

p <- ggplot( c, aes(x=c$a, fill=c$b) ) + geom_histogram( binwidth=0.2 ) + 
    scale_fill_manual(breaks = levels(c$b), values = MyColours, 
                      name = "X Intervals", drop=FALSE)

enter image description here

Related question here.

like image 71
tonytonov Avatar answered Sep 25 '22 18:09

tonytonov