【问题标题】:Other approaches to handle extreme values / distribution when using scale_fill_gradient?使用 scale_fill_gradient 时处理极值/分布的其他方法?
【发布时间】:2013-09-26 00:43:59
【问题描述】:

例如,我想将颜色映射到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,不过好像有点复杂,我只能隐约理解它是怎么工作的。

然后我想也许order 是一个很好的重新调整方式,因此:

ggplot(a,aes(x=x,y=y,fill=ecdf(z)(z))) + geom_bar(stat="identity") +
scale_fill_gradient2(high="green", mid="white", low="red", midpoint=ecdf(a$z)(0))

它在某种程度上起作用(这里我使用ecdf 而不是order 来查找重新缩放的值0。但是,缺点是,我想将图例的标签保留为未缩放的值,而不是重新缩放的那些。所以像labels=function(x) quantile(a$z, x) 这样的东西,我无法让它工作。另外,我发现重复使用ecdfquantile 向前和向后重新缩放是愚蠢的。

在这些情况下是否有更好或更简单的方法,例如足够强大(不需要优化或非常准确),足以为各种映射值的分布填充合理的颜色。

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    据我所知,没有一种简单的方法,但您可以使用scale_fill_gradientn 完全控制映射。关键是将颜色映射到 0-1 范围内的值,其中 0 是最小值,1 是最大值。这是一个选项:

    library(ggplot2)
    a <- data.frame(x=1:10, y=1, z=c(rnorm(8),-12,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, aes(x=x,y=y,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
    

    在这里,我们选择根据值的分布为值分配均匀的插值颜色。因此,如果一个值范围对应于分布的大部分,即使它实际上跨越了最小-最大范围的相对较小部分,它将获得更多的颜色分配。

    如果您想将特定颜色分配为零,您可以通过编辑与 coloursvaluesbreaks 参数对应的向量来实现。如果您在零以上和零以下具有相同数量的值,则这很琐碎,如果没有,则很烦人。


    版本 w/0 设置为白色:

    library(ggplot2)
    a <- data.frame(x=1:10, y=1, z=c(rnorm(8), -12, 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), 0:((splits - 1) / 2) / ((splits - 1) / 2), 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", "white", "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, aes(x=x,y=y,fill=z)) + 
      geom_bar(stat="identity") +
      scale_fill_gradientn(
        colours=colours,
        values=val.remap,
        breaks=quants,
        guide="legend") 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2016-09-16
      相关资源
      最近更新 更多