Peter
Peter

Reputation: 65

R ggplot2 - adjust distance between breaks on a continuous colourbar gradient

I have created a heatmap in ggplot2 using geom_tile and mapped the values using scale_fill_gradientn. The colourbar is separated into two gradients. One gradient maps values from 0 to 0.05, and the other gradient maps values from 0.05 to 1. The heatmap looks as desired but the colourbar is not as desired. I would like the red-yellow gradient (0-0.05) to have identical height as the black-brown gradient (0.05-1).

HEATMAP

QUESTION: How do I modify the colourbar so the value 0.05 is in the middle/center of the bar making the height of the two distinct color gradients identical?

In other words, imagine that the 0.05 tick mark is a slider and you can move it to the middle of the bar expanding/compressing the respective gradients.

Similar questions has been discussed in the two posts below but with no conclusive solution, or at least not the one I can easily understand and answers my question:

Thank you all very much for reading my question and thinking about the possible solutions. I could not figure out anything useful so far except editing the colourbar in Photoshop. Petr



Reproducible example:

TEST <- read.csv ("https://filetea.me/n3wHRhuy0GlS4xvjQDxs95BVA",header=T,row.names=NULL)

library(ggplot2) 
ggplot(TEST, aes(x=Measure, y=SMTSD))+
    geom_tile(aes(fill=Pval),colour="grey50", size=0.1) +
    scale_x_discrete(expand = c(0,0))+
    coord_equal(ratio=1)+

scale_fill_gradientn(colours=c("red","yellow","black","#996633"),
    values=c(0,0.0499,0.05,1),
    na.value="white", guide="colourbar",
    name="P-value",limits=c(0,1),breaks=c(0,0.05,1))+

 guides(fill = guide_colourbar(barheight = 20, direction = "vertical",
        title.position="top", title.hjust = 0.5,title.vjust = 0.5, nbin = 50))

Upvotes: 4

Views: 5169

Answers (2)

NULLOcean
NULLOcean

Reputation: 1

Based on the previous answers, I have a new idea.

That is to map the p-value data to the 0-1 interval and pad the original data by sampling from one side of 0.05 so that 0.05 is in the middle. Then through ecdf(), each p value can have a corresponding 0-1 mapping data, and a p value of 0.05 obtains a median value of 0.5. Then, draw the mapped data, and obtain the p-value before the mapping corresponding to the color through quantile(). Since the data in the question is not available, I provide a new test data.

x <- c(1:10)
y <- c(1:10)
data <- expand.grid(X=x, Y=y)
data$Z <-c(runif(25,0.001,0.05),runif(75,0.06,10))
library(ggplot2) 
ggplot(data, aes(x=X, y=Y))+
  geom_tile(aes(fill=Z), size=0.1) +
  scale_x_discrete(expand = c(0,0))+
  coord_equal(ratio=1)+
  
  scale_fill_gradientn(colours=c("red","yellow","#996633"))

enter image description here

######### map p_value to 0-1

#There are other methods like interpolation, I just use sample() for convenience

length(data$Z)
max(data$Z[data$Z<0.05])
value_in_num_series<-length(data$Z)*ecdf(c(data$Z))(max(data$Z[data$Z<0.05]))
value_in_num_series
NUM<-length(data$Z)-2*value0.05_in_num_series
make_0.05_at_quantile50<-c(sample(data$Z[data$Z<0.05],NUM,replace =T),0.05,data$Z)
ecdf(make_0.05_at_quantile50)(0.05)
quantile(make_0.05_at_quantile50,0.5)
value_trans_list<-NULL
for (i in 1:length(data$Z)) {
  value<-data$Z[i]
  if(is.na(value)){
    value_trans<-NA
  }else{
    value_trans<-ecdf(make_0.05_at_quantile50)(value)
  }
  value_trans_list[[i]]<- value_trans
  
}
data$TransZ<-unlist(value_trans_list)

ggplot(data, aes(x=X, y=Y))+
  geom_tile(aes(fill=TransZ), size=0.1) +
  scale_x_discrete(expand = c(0,0))+
  coord_equal(ratio=1)+
  
  scale_fill_gradientn(colours=c("red","yellow","#996633"),limits=c(0,1),breaks=,c(0,0.25,0.5,0.75,1), 
                       labels=round(quantile(make_0.05_at_quantile50,c(0,0.25,0.5,0.75,1)),2))

result:

enter image description here

Upvotes: 0

Adam Quek
Adam Quek

Reputation: 7153

Changing the scale_fill_gradient values and breaks will give you what you need:

ggplot(TEST, aes(x=Measure, y=SMTSD))+
  geom_tile(aes(fill=Pval^0.2313782),colour="grey50", size=0.1) +
  scale_x_discrete(expand = c(0,0))+
  coord_equal(ratio=1)+
  scale_fill_gradientn(colours=c("red","yellow","black","#996633"),
                       values=c(0,0.0499,0.05,1)^ 0.2313782,
                       na.value="white", guide="colourbar",
                       name="P-value",limits=c(0,1),breaks=c(0,0.05,1)^ 0.2313782, 
                       labels=c(0,0.05,1))+
  guides(fill = guide_colourbar(barheight = 20, direction = "vertical",
                               title.position="top", title.hjust = 0.5,title.vjust = 0.5, nbin = 50))

enter image description here

p.s. edited with new image

Upvotes: 7

Related Questions