3

I am plotting several matrices in ggplot using geom_tile(). I'm using colors to represent the value variable (i.e. the fill). All data are in one dataframe. I am trying to get the range of colors in the fill to be scaled uniquely for each element/marix of the plot. Using facet_wrap() currently, it finds the highest value across all plots and assigns that as the 'high' value. Likewise it finds the lowest value for the 'low' value.

I've tried using scales='free' in the facet_wrap() but that isn't logical (and doesn't work). Essentially I want it to assign the high and low values for the fill based on the highest and lowest value within each group. I don't want to make every plot individually as I have dozens of plots.

Here is some sample data:

library(ggplot2) set.seed(110)

dfA <- data.frame(Var1=rep(LETTERS[1:5],5), Var2=rep(LETTERS[1:5],each=5), Value=sample(1:30, replace=T, 25), Group="A")
dfB <- data.frame(Var1=rep(LETTERS[1:5],5), Var2=rep(LETTERS[1:5],each=5), Value=sample(15:60, replace=T, 25), Group="B")
dfC <- data.frame(Var1=rep(LETTERS[1:5],5), Var2=rep(LETTERS[1:5],each=5), Value=sample(1:99, replace=T, 25), Group="C")
dfX <- rbind(dfA,dfB,dfC)

Here I plot three tiled plots using facet_wrap() :

ggplot(dfX, aes(Var1, Var2, fill = Value)) + 
  geom_tile(colour="white", size=1.75, stat="identity") + 
  scale_fill_gradient(low = "white", high = "red") +
  geom_text(data=dfX, aes(Var1, Var2, label = Value), color="black", size=rel(5)) +
  facet_wrap(~Group)

enter image description here

The above plot is not ideal as the first two matrices should have the same fill scale as the final matrix even though their number distributions are lower in range. Ideally, I'd like a solution that isn't just ranging the data for each group between 0-1 e.g using the formula zi=xi−min(x) / max(x)−min(x)

tonytonov
  • 25,060
  • 16
  • 82
  • 98
jalapic
  • 13,792
  • 8
  • 57
  • 87
  • You could create three separate plots and use gridExtra/gridArrange to combine them. `facet_`... plots have one legend/fill scale. – Heroka Nov 25 '15 at 08:21

1 Answers1

2

Within the constraints of not creating a 'range' variable and being accomodating of multiple plots, here is (a start of) a solution. It doesn't use facetting, as facets share color/fill/...-scales. I found an old comment of hadley wickham on a feature request for this, and it was ".. extremely unlikely, because it's easy to work around by drawing separate plots" source

As your scales vary per plot and seem to have no need for a legend (as all the values are in the plot), I've removed all legends. It can be used for as many plots as you want, just edit the arguments to grid.arrange.

library(gridExtra)
#create lots of plots by using lapply/split --> easily scalable to many plots 

myplots <- lapply(split(dfX, dfX$Group), function(x){
  p1 <- ggplot(x, aes(Var1, Var2, fill = Value)) + 
    geom_tile(colour="white", size=1.75, stat="identity") + 
    scale_fill_gradient(low = "white", high = "red") +
    geom_text(aes(Var1, Var2, label = Value), 
              color="black", size=rel(5)) +
    labs(title=unique(x$Group)) +
    theme(legend.position="none")
}
)

do.call(grid.arrange,c(myplots, ncol=3))

enter image description here

Community
  • 1
  • 1
Heroka
  • 12,889
  • 1
  • 28
  • 38