Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Centering color around 0 with RColorBrewer

Tags:

plot

r

image

So I want to visualise a matrix with colors like this

library(RColorBrewer)
vec = rbinom(10000,1,0.1)
n = sum(vec)
vec = ifelse(vec == 1, rnorm(n), 0)
mat = matrix(vec,100,100)
image(t(mat)[,nrow(mat):1],
      col=brewer.pal(8,"RdBu"),
      xaxt= "n", yaxt= "n", frame.plot=T,
      useRaster = TRUE
)

Which gives me the plot

Example plot

But I want the colors to be "centered around 0". By that I mean that I want the value zero to be white and positive/negative values be red/blue (or blue/red it doesn't matter). Any ideas if this is possible?

like image 814
Robin Lindström Avatar asked May 17 '18 19:05

Robin Lindström


2 Answers

The function bluered in the gplots package does this. You can make your color palette as:

library(gplots) # not to be confused with `ggplot2`, which is a very different package
color_palette <- bluered(9) # change the number to adjust how many shades of blue/red you have.  Even numbers will assign white to two bins in the middle.

To force them to be centered in the middle, you might use the heatmap.2 function, also in gplots - just don't have it do any clustering:

heatmap.2(mat,
  Rowv = FALSE,
  Colv = FALSE, 
  dendrogram = 'none',
  trace = 'none',
  col = bluered, # this can take a function
  symbreaks = TRUE, # this is the key  value for symmetric breaks
)

to stick with the image function, you need to manually set the breaks. The following code will get that for you:

pos_breaks <- quantile(abs(mat), probs = seq(0, 1, length.out = 5))
centered_breaks <- c(rev(-pos_breaks[-1]), pos_breaks)
like image 114
Melissa Key Avatar answered Sep 19 '22 07:09

Melissa Key


Here is a solution without any additional packages. In your code you did not assign the values from the vec variable to any of the eight color bins. You need to cut the vec array into your eight bins and then assign each bin to a color and then plot:

library(RColorBrewer)
vec = rbinom(10000,1,0.1)
n = sum(vec)
vec = ifelse(vec == 1, rnorm(n), 0)
mat = matrix(vec,100,100)

#cut the original data into 9 groups
cutcol<-cut(vec, 9)
#Create color palette with white as the center color
colorpal<-brewer.pal(8,"RdBu")
colorpal<-c(colorpal[1:4], "#FFFFFF", colorpal[5:8])

#assign the data to the 9 color groups
color<-colorpal[cutcol]
#create the color matrix to match the original data
colormat<-matrix(color,100,100)

#plot with the assigned colors
image(t(mat)[,nrow(mat):1],
      col=colormat,
      xaxt= "n", yaxt= "n", frame.plot=T,
      useRaster = TRUE
)

#check color assignment
#hist(vec)
#hist(as.numeric(cutcol), breaks=8)

enter image description here

like image 27
Dave2e Avatar answered Sep 21 '22 07:09

Dave2e