例如,我想将颜色映射到z,将0映射映射到“白色”.
> a <- data.frame(x=1:10,y=1,z=c(rnorm(8),-12,12)) > a x y z 1 1 1 -0.4603911 2 2 1 -0.4868471 3 3 1 0.2180346 4 4 1 -0.8807652 5 5 1 1.7379462 6 6 1 -0.1334904 7 7 1 -0.3675578 8 8 1 0.9225425 9 9 1 -12.0000000 10 10 1 12.0000000 ggplot(a,aes(x=x,y=y,fill=z)) + geom_bar(stat="identity") + scale_fill_gradient2(high="green",mid="white",low="red")
正如你所看到的那样,颜色并不是真正有用的指标,而不是传达关于值如何分布的一般概念,现在颜色只能告诉哪些值是极端的,留下大多数值无法区分未经训练的眼睛.
有一个方法Non-linear color distribution over the range of values in a geom_raster但似乎有点复杂,我只能模糊地理解它是如何工作的.
然后我想也许顺序是一个很好的重新缩放方式,因此:
ggplot(a,fill=ecdf(z)(z))) + geom_bar(stat="identity") + scale_fill_gradient2(high="green",low="red",midpoint=ecdf(a$z)(0))
它在某种程度上起作用(这里我使用ecdf而不是命令来找到重新调整的值0.但是,缺点是,我想将图例的标签保持为未缩放的值,而不是重新缩放的值.所以像labels = function(x)quantile(a $z,x),我无法使它工作.而且,我发现重复使用ecdf和quantile来向前和向后重新缩放是很愚蠢的.
在这些情况下是否有更好或更简单的方法,例如强大的(不需要是最佳的或非常准确的)足以为各种映射值分布填充合理的颜色.
解决方法
我知道并不是一种简单的方法,但您可以使用scale_fill_gradientn完全控制映射.关键是将颜色映射到0-1范围内的值,其中0是您的最小值,1是您的最大值.这是一个选项:
library(ggplot2) a <- data.frame(x=1:10,12)) get_col <- colorRamp(c("red","white","green")) # make fun to interpolate colors quantiles <- (0:6) / 6 # how many quantiles we want to map quantile.vals <- quantile(a$z,quantiles,names=F)# the values for each quantile colours <- rgb(get_col(quantiles),max=255) # 7 evenly interpolated colors val.remap <- (quantile.vals - min(a$z)) / diff(range(a$z)) # The values corresponding to the quantiles ggplot(a,fill=z)) + geom_bar(stat="identity") + scale_fill_gradientn( colours=colours,values=val.remap,breaks=quantile.vals,# Necessary to get legend values spread appropriately guide="legend") # Necessary to get legend values spread appropriately
在这里,我们选择根据值的分布将均匀插值的颜色分配给值.因此,如果值范围对应于分布的大部分,即使它实际跨越最小 – 最大范围的相对小部分,它将获得更多颜色分配.
如果要将特定颜色指定为零,可以通过编辑与颜色,值和中断参数对应的矢量来实现.如果您具有高于和低于零的相同数量的值,则这是微不足道的,如果不是则令人讨厌.
版本w / 0设置为白色:
library(ggplot2) a <- data.frame(x=1:10,12)) splits <- 7 # should be odd number mid.point <- 0 pos.vals <- a$z[a$z > mid.point] neg.vals <- a$z[a$z < mid.point] pos.quants <- quantile(c(mid.point,pos.vals),0:((splits - 1) / 2) / ((splits - 1) / 2),names=F) neg.quants <- quantile(c(mid.point,neg.vals),names=F) quants <- c(neg.quants,pos.quants[-1]) # drop of the mid-point from pos.quants since otherwise double counted get_col <- colorRamp(c("red","green")) # make fun to interpolate colors colours <- rgb(get_col(0:(splits - 1)/(splits - 1)),max=255) # 7 evenly interpolated colors val.remap <- (quants - min(quants)) / diff(range(quants)) # The values corresponding to the quantiles ggplot(a,breaks=quants,guide="legend")