How to set fixed continuous colour values in ggplot2

Do I understand this correctly? You have two plots, where the values of the color scale are being mapped to different colors on different plots because the plots don't have the same values in them.

library("ggplot2")
library("RColorBrewer")
ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) + 
  geom_point(size=6)

enter image description here

ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) + 
  geom_point(size=6)

enter image description here

In the top one, dark blue is 1 and light blue is 4, while in the bottom one, dark blue is (still) 1, but light blue is now 8.

You can fix the ends of the color bar by giving a limits argument to the scale; it should cover the whole range that the data can take in any of the plots. Also, you can assign this scale to a variable and add that to all the plots (to reduce redundant code so that the definition is only in one place and not in every plot).

myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
sc <- scale_colour_gradientn(colours = myPalette(100), limits=c(1, 8))

ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) + 
  geom_point(size=6) + sc

enter image description here

ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) + 
  geom_point(size=6) + sc

enter image description here


There may be a better way to do this, but I don't know of it. In the meantime, you need to make sure that the values argument of scale_colour_gradientn is such that the values of all your plots map to the correct colors. So here, I make two plots with the same mapping between 0-100, but one of them has values from 50-150:

mydata <- data.frame(X=runif(20), Y=runif(20), Z=runif(20, 0, 100))
p1 <- ggplot(mydata, aes(x=X, y=Y, colour=Z)) + 
  geom_point(alpha=.5, size = 6) + 
  scale_colour_gradientn(colours = myPalette(100), values=seq(0, 100, length.out=100)/100) + 
  ggtitle("Z: 0 - 100")

This is the key bit:

mydata2 <- data.frame(X=runif(20), Y=runif(20), Z=runif(20, 50, 150))
nrm.range.2 <- (range(mydata$Z) - min(mydata2$Z)) / diff(range(mydata2$Z))
nrm.vals <- seq(nrm.range.2[[1]], nrm.range.2[[2]], length.out=100)

Now make the second plot.

p2 <- ggplot(mydata2, aes(x=X, y=Y, colour=Z)) + 
  geom_point(alpha=.5, size = 6) + 
  scale_colour_gradientn(colours = myPalette(100), values=nrm.vals) + 
  ggtitle("Z: 50 - 150")

enter image description here

I don't know of anyway of forcing which range of value display on the scale, but to the extent you have multiple plots with non-overlapping ranges of Z values, you can create a third dummy plot with all the range and use that. Here I purposefully went off range to show that the values that overlap have the same colors.


Ok so taking the data set from the previous example:

library(ggplot2)
library(RColorBrewer)
library(gridExtra)
library(gtablegridExtra)

#Using the mtcars data set

#Generate plot 1
p1=ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) + 
          geom_point(size=2)+
          labs(title="Graph 1")+
          scale_color_gradientn(colours=rainbow(5))

#Generate plot 2
p2=ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) + 
          geom_point(size=2)+
          labs(title="Graph 2")+
          scale_color_gradientn(colours=rainbow(5)) 

So if we plot both graphs together using grid.arrange you should get this:

grid.arrange(arrangeGrob(p1,
                         p2,
                         nrow = 1))

Graphs without equivalent color scale

So we want to get the same range for both graphs and plot only one of this colos sacles. What you need to do is first define the range of the of your color scale. in this example lets do it from:

summary(mtcars$carb)

>
Min.   1st Qu.  Median  Mean   3rd Qu.   Max. 
1.000   2.000   2.000   2.812   4.000   8.000 

So we know that the color scale should be from 1 to 8. We define this range as col.range and we then use it to specify the range in each graph:

#Define color range
col.range=c(1,8)

#Generate plot 1
p1=ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) + 
          geom_point(size=2)+
          labs(title="Graph 1")+
          scale_color_gradientn(colours=rainbow(5),limits=col.range) #look here

#Generate plot 2
p2=ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) + 
          geom_point(size=2)+
          labs(title="Graph 2")+
          scale_color_gradientn(colours=rainbow(5),limits=col.range) #look here 


#Plot both graphs together
 grid.arrange(arrangeGrob(p1,
                          p2,
                          nrow = 1))

This will get you the following graph. Now the color is comparable between both graphs.

Graphs with same color scale

However the repeated colos scale is redundant, so we want to use only one.

So to get that nice final graph we can use the same p1 and p2 graphs that we defined previously, we just especified on the grid.arrange function as:

#Create al element that will represent your color scale:
color.legend=gtable_filter(ggplotGrob(p1),"guide-box")

#We hide de color scale on each individual graph
#Then we insert the color scale and we adjust the ratio of it with the graphs
#For this we define the theme() as follows:

grid.arrange(arrangeGrob(p1+theme(legend.position="none"),
                         p2+theme(legend.position="none"),
                         nrow = 1), #Here we have just remove the color scale
             color.scale, #We inserted the color scale. 
             nrow=1, #We put the color scale to the right of the graph
             widths=c(20,1) #With this we make the color scale much narrower

So with this you are done, getting the following graph:

Graphs with just one color scale

Hope is is usefull!!!!!!

Please rate!!!!! <3