在没有 ggplot2 的情况下绘制堆栈的渐变颜色

plot gradient colours of stack without ggplot2

我想用渐变颜色绘制我的栅格图层 (b1_mosaic_diff):负值应从黄色变为红色,正数应从浅蓝色变为深蓝色。

我有一个代码示例,不幸的是它没有工作(而不是渐变红色我把 heat.colorstopo.colors 一样用于渐变蓝色:

plot(b1_mosaic_diff, col=ifelse(na.omit(as.data.frame(b1_mosaic_diff))<0, heat.colors(n=5), topo.colors(n=5)), main="Difference between mean & median: '+' representing higher mean")

我不想使用 ggplot,因为我更容易坚持使用普通绘图。有可能做到这一点吗? 提前致谢!

这有点繁琐,但我通常会生成 n(例如 1000)种颜色,其中每一种都具有两种互补的 colourRampPalette 颜色(例如,一种由 reds/yellows 构成,另一种由 reds/yellows 构成蓝调)。之后,如果颜色键的长度在零的任一侧都不是偶数,我根据颜色键的长度与键的较长端的比例(这更容易用下面的例子解释)。最后,我连接两个颜色向量并将其传递给 rasterVis::levelplotcol.regions 参数。

这是一个例子:

  1. 加载所需的库并创建虚拟栅格:

    library(raster)
    library(RColorBrewer)
    library(rasterVis)
    
    r <- raster(matrix(runif(100, -5, 10), 10))
    
  2. 创建颜色矢量。在这里,我使用 RColorBrewer 调色板 'YlOrRd'(我将其反转为红色 > 橙色 > 黄色,因为颜色按照从最负到最正的顺序与光栅值相关联),并且 'Blues'。这些调色板每个只提供 9 种颜色,因此我们将调色板传递给 colorRampPalette 以生成许多中间(插值)颜色。在这里,我为每个调色板生成 1000 种颜色 - 这足以创建平滑的色键。

    我们希望颜色键跨越栅格数据集中的值范围,范围从 -5 到 10。因此,我们需要对将用于颜色的短臂的颜色矢量进行子集化键(负值,即红色)。确切地说,我们想要删除 reds 向量的前 500 个值,因为键的 <0 部分是 >0 部分长度的一半。这给我们留下了 500 orange-yellows 的矢量(我们去掉了最红的红色)和 1000 蓝色的矢量。

    cols <- c(colorRampPalette(rev(brewer.pal(9, 'YlOrRd')))(1000)[501:1000], 
              colorRampPalette(brewer.pal(9, 'Blues'))(1000))
    
  3. 使用 levelplot 绘制栅格,这比 raster 对象的常规绘图方法更灵活。为了方便起见,我们首先创建一个下限和上限向量 (z-limits)。

    zrng <- range(pretty(c(minValue(r), maxValue(r))))
    
    levelplot(r, margin=FALSE, at=seq(zrng[1], zrng[2], diff(zrng)/1000),
              col.regions=cols, scales=list(draw=FALSE))
    

  4. 额外练习!

    要使向量 sub-setting 自动化,您可以使用以下函数:

    asym_colours <- function(r, pal1, pal2, n=2000) {
      zrng <- range(pretty(c(minValue(r), maxValue(r))))
      brks <- do.call(seq, as.list(c(max(abs(zrng)) * c(-1, 1), length.out=2*n)))
      c(pal1(n)[(sum(brks < zrng[1]) + 1):n], 
        pal2(n)[1:(sum(brks < zrng[2] & brks > 0) + 1)])  
    }
    

    例如:

    r <- raster(matrix(runif(100, -0.3, 0.1), 10))    
    cols <- asym_colours(r, colorRampPalette(rev(brewer.pal(9, 'YlOrRd'))),
                         colorRampPalette(brewer.pal(9, 'Blues')))
    zrng <- range(pretty(c(minValue(r), maxValue(r))))
    levelplot(r, margin=FALSE, at=seq(zrng[1], zrng[2], diff(zrng)/1000),
              col.regions=cols, scales=list(draw=FALSE))
    

    或者,使用不同的斜坡:

    cols <- asym_colours(r, colorRampPalette(rev(brewer.pal(9, 'GnBu'))),
                         colorRampPalette(brewer.pal(9, 'PuRd')))
    zrng <- range(pretty(c(minValue(r), maxValue(r))))
    levelplot(r, margin=FALSE, at=seq(zrng[1], zrng[2], diff(zrng)/1000),
              col.regions=cols, scales=list(draw=FALSE))