R ggplot2 - 调整连续色条渐变中间断点之间的距离

4
我已经使用geom_tile创建了一个热力图,并使用scale_fill_gradientn映射了值。颜色条被分为两个梯度。一个梯度将值从0映射到0.05,另一个梯度将值从0.05映射到1。热图看起来很好,但颜色条不理想。我希望红-黄渐变(0-0.05)的高度与黑-棕渐变(0.05-1)的高度相同。

HEATMAP

问题: 如何修改色条,使值0.05位于条的中间/中心,使两个不同颜色梯度的高度相同?换句话说,想象一下0.05刻度标记是一个滑块,您可以将其移动到条的中间,扩展/压缩相应的渐变。

类似的问题在以下两篇帖子中讨论过,但没有确定的解决方案,或者至少不是我可以轻松理解并回答我的问题:

非常感谢大家阅读我的问题并思考可能的解决方案。到目前为止,除了在Photoshop中编辑色条之外,我什么有用的东西都想不出来。Petr



可重现的例子:

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))
2个回答

6
改变scale_fill_gradient的值和分界点(breaks)将会得到你需要的结果:
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))

图片描述

附:图片已更新


感谢 @Adam Quek 的迅速而出色的回复。请问您能否解释一下在 values=c(0,0.0499,0.05,1)^.25 中使用 ^.25 的含义? - Peter
1
@zacdav 我想是吧。我只是在脑算,但是没错,0.05^0.2313782=0.5 - Adam Quek
3
他将数值转换为在0到1之间的比例,因为你只有一个断点(即将改变的断点),他将0.05重新缩放为0.5,满足0.05^x = 0.50。 - zacdav
经过仔细检查,我发现@AdamQuek生成的热图存在问题。变换某种方式改变了映射到瓷砖上的值。例如,在测量S中,急性髓性白血病的原始值为0.32,但在Adam的解决方案中,它被映射为< 0.05.相同的值在原始绘图中被正确地映射(黑色> 0.05)。有没有办法解决这个问题? - Peter
1
在你的geom_tile中使用相同的处理方式,即 geom_tile(aes(fill=Pval^0.2313782),colour="grey50", size=0.1) - Adam Quek
显示剩余2条评论

0

根据之前的答案,我有一个新的想法。

那就是将p值数据映射到0-1区间,并通过从0.05的一侧进行抽样来填充原始数据,使得0.05位于中间。然后通过ecdf(),每个p值都可以有一个对应的0-1映射数据,而0.05的p值获得0.5的中位数。 接下来,绘制映射数据,并通过quantile()获取映射之前对应颜色的p值。 由于问题中的数据不可用,因此我提供了新的测试数据。

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

######### 将 p_value 映射到 0-1

#还有其他方法,比如插值法,我只是为了方便起见使用了 sample() 函数

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))

结果:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接