'Levelplot color key - range and extremes

Is it possible in R to create a color key like the one below? (this one comes from the software Grid Analysis and Display System - Grads).

enter image description here

There are two features that I can't reproduce in R:

  1. The sequence is non linear however it is displayed as if
  2. Values bigger than 200 are grey / Values smaller than 0 are white

I'm using levelplot from rastervis that plots rasters using the lattice levelplot:

require(raster)
require(rasterVis)

set.seed(200)

X = seq(-40,0,by=1)
Y = seq(-60,-40,by=1)
grid = expand.grid(list(X=X,Y=Y))
Z = rnorm(nrow(grid),mean=10,sd=100)

data = data.frame(grid,Z)
r = rasterFromXYZ(data)
mapTheme <- rasterTheme(region=c('#EEF7FA','#D6F8F7',"#BEDAFF",'#5DA4FF',"#0000FF","#D4F9E2","#00FF7F","#008000","#FFFF00","#FFD27F", "#FFB732"    ,"#EE7600",
                                 "#D53E4F","#FF6A6A"))  
my.at = c(0,1,5,10,15,20,25,30,40,50,75,100,150,200)
myColorkey <- list(at=my.at,
                   space="bottom",
                   labels=list(at=my.at))
p=levelplot(r, par.settings=mapTheme,at = my.at, colorkey=myColorkey,margin=F)
print(p)

The result:

enter image description here

As you can see, both values smaller than 0 and bigger than 200 are white, I've no idea how to set values bigger than or smaller than a certain value to appear as a specific color. Morover, how can I make the space between consecutive thick marks in the color key to have the same size although the intervals are not the same?



Solution 1:[1]

This is a workaround for equally sized intervals for non linear sequences:

library(raster)
library(rasterVis)

set.seed(200)
X = seq(-40,0,by=1)
Y = seq(-60,-40,by=1)
grid = expand.grid(list(X=X,Y=Y))
Z = rnorm(nrow(grid),mean=10,sd=100)

data = data.frame(grid,Z)
r = rasterFromXYZ(data)
mapTheme <- rasterTheme(region=c('#EEF7FA','#D6F8F7',"#BEDAFF",'#5DA4FF',"#0000FF","#D4F9E2","#00FF7F",
                                 "#008000","#FFFF00","#FFD27F", "#FFB732" ,"#EE7600", "#D53E4F","#FF6A6A"))  

my.at=c(0,1,5,10,15,20,25,30,40,50,75,100,150,200)
my.brks=seq(0, 200, by=15)

myColorkey <- list(at=my.brks, labels=list(at=my.brks, labels=my.at), space="bottom")
p=levelplot(r, par.settings=mapTheme, at=my.at, colorkey=myColorkey, margin=F)
print(p)

enter image description here

This could be a solution for values smaller 0 and greater than 200:

library(raster)
library(rasterVis)

set.seed(200)
X = seq(-40,0,by=1)
Y = seq(-60,-40,by=1)
grid = expand.grid(list(X=X,Y=Y))
Z = rnorm(nrow(grid),mean=10,sd=100)

data = data.frame(grid,Z)
r = rasterFromXYZ(data)
mapTheme <- rasterTheme(region=c('white','#EEF7FA','#D6F8F7',"#BEDAFF",'#5DA4FF',"#0000FF","#D4F9E2","#00FF7F",
                                 "#008000","#FFFF00","#FFD27F", "#FFB732" ,"#EE7600", "#D53E4F","#FF6A6A", "gray"))  
max(values(r))
min(values(r))

my.at=c(min(values(r)), 0,1,5,10,15,20,25,30,40,50,75,100,150,200, max(values(r)))
my.brks=seq(0, 200, by=13)

myColorkey <- list(at=my.brks, labels=list(at=my.brks, labels=c(-276,0,1,5,10,15,20,25,30,40,50,75,100,150,200, 388)), space="bottom")
p=levelplot(r, par.settings=mapTheme, at=my.at, colorkey=myColorkey, margin=F)
print(p)

enter image description here

Your colors are not progressing from light to dark. You can use the RColorBrewer package to fix this.

library(RColorBrewer)
reds = brewer.pal(5, "YlOrRd")
greens = brewer.pal(3, "Greens")
blues = brewer.pal(5, "Blues")
mapTheme <- rasterTheme(region=c('white', blues, greens, reds, "gray"))

enter image description here

Solution 2:[2]

This is a very helpful workaround. While not addressing question 1, something I found useful for question 2 (adding triangles for values below/above the limits of the colorbar range) can be achieved by adding this:

library(s2dverification)
data_array <- array(Z, dim = c(length(X), length(Y)))
PlotEquiMap(data_array, X, Y,bar_limits=c(0,200),col_inf='white',col_sup='gray')

raster with colorbar

Solution 3:[3]

Another solution with updates to lattice:

library(raster)
library(rasterVis)

set.seed(200)
X = seq(-40,0,by=1)
Y = seq(-60,-40,by=1)
grid = expand.grid(list(X=X,Y=Y))
Z = rnorm(nrow(grid),mean=10,sd=100)
data = data.frame(grid,Z)
r = rasterFromXYZ(data)

levelplot(r, margin=F, at=c(-Inf, seq(0, 200, 20), Inf),
          colorkey = list(tri.lower = TRUE, tri.upper = TRUE))

rastervis_levelplot

As long as you add "-Inf" and "Inf" to your at definition, the option to add triangles to the colorbar is activated.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 EdM
Solution 3 EdM