绘制色带在零附近发散的栅格
Posted
技术标签:
【中文标题】绘制色带在零附近发散的栅格【英文标题】:Plotting a raster with the color ramp diverging around zero 【发布时间】:2016-02-18 10:16:46 【问题描述】:我正在尝试绘制具有正值和负值的地图。
所有正值都应该是红色,负值应该是蓝色,零应该是白色,就像在这个带有离散颜色的示例图中一样
下面是我正在使用的代码:
library (rasterVis)
ras1 <- raster(nrow=10,ncol=10)
set.seed(1)
ras1[] <- rchisq(df=10,n=10*10)
ras2=ras1*(-1)/2
s <- stack(ras1,ras2)
levelplot(s,par.settings=RdBuTheme())
非常感谢您提供了一个通用的解决方案,该解决方案也可以应用于其他映射练习。
【问题讨论】:
你已经问过类似的问题了:***.com/questions/33748871/… @Pascal 问题几乎相似。但是,这个使用了不同的调色板,我希望白色表示零值,如上图所示。另一个问题改为使用 RdYIBu 调色板。感谢您的帮助。 您的大部分代码与您的问题无关。请提供一个简单的可重现示例,仅包含相关代码。例如。从r <- raster(); values(r) <- 10* (runif(ncell(r)) - 0.5)
开始
@RobertH 感谢您建议我改进可重现的示例和代码。这是更合适的内容:ras1 <- raster(nrow=10,ncol=10) set.seed(1) ras1[] <- rchisq(df=10,n=10*10) ras2=ras1*(-1)/2 s <- stack(ras1,ras2) levelplot(s,par.settings=RdBuTheme())
。如上图所示,如何将 0 设置为红色和蓝色的分界点?
【参考方案1】:
我写了a gist 来做这件事。它采用由rasterVis::levelplot
生成的trellis
对象和一个色带,并绘制颜色在零附近发散的对象。
使用您的s
,您可以这样使用它:
devtools::source_gist('306e4b7e69c87b1826db')
p <- levelplot(s)
diverge0(p, ramp='RdBu')
ramp
应该是RColorBrewer
调色板的名称、要插值的颜色向量或colorRampPalette
。
来源:
diverge0 <- function(p, ramp)
# p: a trellis object resulting from rasterVis::levelplot
# ramp: the name of an RColorBrewer palette (as character), a character
# vector of colour names to interpolate, or a colorRampPalette.
require(RColorBrewer)
require(rasterVis)
if(length(ramp)==1 && is.character(ramp) && ramp %in%
row.names(brewer.pal.info))
ramp <- suppressWarnings(colorRampPalette(brewer.pal(11, ramp)))
else if(length(ramp) > 1 && is.character(ramp) && all(ramp %in% colors()))
ramp <- colorRampPalette(ramp)
else if(!is.function(ramp))
stop('ramp should be either the name of a RColorBrewer palette, ',
'a vector of colours to be interpolated, or a colorRampPalette.')
rng <- range(p$legend[[1]]$args$key$at)
s <- seq(-max(abs(rng)), max(abs(rng)), len=1001)
i <- findInterval(rng[which.min(abs(rng))], s)
zlim <- switch(which.min(abs(rng)), `1`=i:(1000+1), `2`=1:(i+1))
p$legend[[1]]$args$key$at <- s[zlim]
p$par.settings$regions$col <- ramp(1000)[zlim[-length(zlim)]]
p
请注意,正如@LucasFortini 的post 中所建议的那样,如果您愿意让颜色键在零上下相同的距离,例如:levelplot(s,par.settings=RdBuTheme(), at=seq(-max(abs(cellStats(s, range))), max(abs(cellStats(s, range))), len=100))
,则该过程会简单得多。
【讨论】:
jbaums 在点。分歧0 是最想要的代码。你这很有创意。 嗨 jbaums 我如何在下面的代码中定义颜色的数量?那就是我希望diverge0
中的颜色条与p
中的级别相同。目前它看起来像 1001 种颜色,但我需要 10 种。devtools::source_gist('306e4b7e69c87b1826db') Uniques <- cellStats(s,stat=unique) Uniques.max <- max(Uniques) Uniques.min <- min(Uniques) my.at <- round(seq(ceiling(Uniques.max), floor(Uniques.min), length.out = 10),0) myColorkey <- list(at=my.at, ## where the colors change labels=list(at=my.at)) p <- levelplot(s,at=my.at, colorkey=myColorkey) diverge0(p, ramp='RdBu')
@aez849 - 这些中断有点奇怪,但对于这样的情况,“手动”计算颜色矢量会更容易。例如。 levelplot(s, at=my.at, col.regions=colorRampPalette(brewer.pal(11, 'RdBu'))(12)[4:12], colorkey=myColorkey)
。有 6 个正分箱和 3 个负分箱,因此我们可以沿RdBu
渐变创建一个包含 12 种颜色的向量(使用colorRampPalette(brewer.pal(11, 'RdBu'))(12)
),并排除前 3 个(即元素4:12
的子集)。
@jbaums 有没有一种方法可以使用您的功能,但也可以设置应该使用一种颜色的上限,例如黄色,表示饱和度?
@jbaums,我刚刚发布了一个关于调整您的发散比例以使其非线性的问题:***.com/questions/55172091/… 也许您有想法?【参考方案2】:
这是我经常用下面的脚本做的事情:
library(colorRamps)
col5 <- colorRampPalette(c('blue', 'gray96', 'red')) #create color ramp starting from blue to red
color_levels=20 #the number of colors to use
max_absolute_value=0.4 #what is the maximum absolute value of raster?
plot(img, col=col5(n=color_levels), breaks=seq(-max_absolute_value,max_absolute_value,length.out=color_levels+1) , axes=FALSE)
使用来自here 的数据,这是一个示例输出和实际脚本:
library(raster)
library(colorRamps)
mask_data=shapefile("D:/temp/so/Main_Hawaiian_Islands_simple3.shp")
img=raster("D:/temp/so/PPT_wet_minus_dry.tif")
col5 <- colorRampPalette(c('blue', 'gray96', 'red')) #create color ramp starting from blue to red
color_levels=10 #the number of colors to use
max_absolute_value=max(abs(c(cellStats(img, min), cellStats(img, max)))) #what is the maximum absolute value of raster?
color_sequence=seq(-max_absolute_value,max_absolute_value,length.out=color_levels+1)
plot(img, col=col5(n=color_levels), breaks=color_sequence, axes=FALSE)
plot(mask_data, add=T)
这可能会打扰一些人,因为在负值范围内有很多未使用的颜色箱(如您提供的示例)。下面的修改允许从地图图例中排除空颜色:
n_in_class=hist(img, breaks=color_sequence, plot=F)$counts>0
col_to_include=min(which(n_in_class==T)):max(which(n_in_class==T))
breaks_to_include=min(which(n_in_class==T)):(max(which(n_in_class==T))+1)
plot(img, col=col5(n=color_levels)[col_to_include], breaks=color_sequence[breaks_to_include] , axes=FALSE)
plot(mask_data, add=T)
【讨论】:
!很好的答案,但如果我的数据在两端具有相同的 abs(max) 值,则非常适合。非常感谢。 我认为这种方法适用范围更广。我这样说是因为在大多数情况下,如果你想要一个以零为中心的色标,而在零周围没有这种对称性,那么在没有仔细检查比例的情况下生成的地图会给出偏离零的偏斜视觉(即深蓝色不是从零到深红色)。 这是真的,尤其是在制作我所追求的气候地图时。在我的情况下,数据从 -10 到 40。举个例子,我如何使用您上面的建议来产生一个可以传达最多信息的发散色放大器?感谢您提供示例。 我认为我上面提供的地图的作者使用了您在此处描述的技术。请使用此问题提供的示例或您自己的示例来演示如何获得上面显示的地图上的颜色条。谢谢。 @LucasFortini: 深蓝色不像深红色那样远离零 - 请注意,在我发布的示例中,坡道的下端是 不是“深红色”。 IE。斜坡被截断以匹配数据。以上是关于绘制色带在零附近发散的栅格的主要内容,如果未能解决你的问题,请参考以下文章