Search code examples
rmapsrasterr-rasterlevelplot

Match particular values with specific color in colorkey levelplot R


library(raster)
library(rasterVis)

I would like to make a custom colorkey for my map. My data spans both negative and positive values. Here is what I have tried to do:

    myat = unique(c(seq( -0.1497458,0,length=6),seq(0,0.1665365,length=6)))
        themes<- colorRampPalette((c("darkred", "red3","red","orange", "yellow","yellow4")))#(length(myat)-1)

myColorkey <- list(at=myat,space = "bottom",labels=list(cex=1,font=1,at=myat),height=1,width=1)
if (dev.cur() == 1) x11(width=4,height=4)

#s <- stack(Precip_DJF,Precip_DJFsim)
levelplot(Precip_DJFtmindiff, layout=c(1, 1), col.regions=themes, 
          colorkey=myColorkey,margin=FALSE,xlab=NULL,ylab=NULL,par.strip.text=list(cex=0),scales=list(x=list(draw=FALSE),y=list(draw=FALSE)))

Results: enter image description here

Question: How can I match the value 0 to yellow color and then place colorkey labels at midpoints of breaks instead of edges? I need cuts=10.

Thanks, AT.

reproducible example here


Solution

  • In this book I provide an example to solve this question. My answer is mostly a copy of part of that example.

    Because you don't provide a dataset to reproduce your code I will use the file proposed in the book:

    library(rasterVis)
    
    setwd(tempdir())
    myURL <-'https://github.com/oscarperpinan/spacetime-vis/raw/master/data/'
    download.file(paste0(myURL,'SISav.grd'), 'SISav.grd', method = 'wget')
    download.file(paste0(myURL,'SISav.gri'), 'SISav.gri', method = 'wget')
    
    SISav <- raster('SISav')
    

    Next lines define the diverging palette:

    meanRad <- cellStats(SISav, 'mean')
    SISav <- SISav - meanRad
    ## Modify the palette with your colors
    divPal <- brewer.pal(n=9, 'PuOr')
    divPal[5] <- "#FFFFFF"
    divTheme <- rasterTheme(region=divPal)
    
    rng <- range(SISav[])
    ## Number of desired intervals
    nInt <- 15
    ## Increment corresponding to the range and nInt
    inc0 <- diff(rng)/nInt
    ## Number of intervals from the negative extreme to zero
    n0 <- floor(abs(rng[1])/inc0)
    ## Update the increment adding 1/2 to position zero in the center of an interval
    inc <- abs(rng[1])/(n0 + 1/2)
    ## Number of intervals from zero to the positive extreme
    n1 <- ceiling((rng[2]/inc - 1/2) + 1)
    ## Collection of breaks
    breaks <- seq(rng[1], by=inc, length= n0 + 1 + n1)
    ## Midpoints computed with the median of each interval
    idx <- findInterval(SISav[], breaks, rightmost.closed=TRUE)
    mids <- tapply(SISav[], idx, median)
    ## Maximum of the absolute value both limits
    mx <- max(abs(breaks))
    ## Interpolating function that maps colors with [0, 1]
    ## rgb(divRamp(0.5), maxColorValue=255) gives "#FFFFFF" (white)
    break2pal <- function(x, mx, pal){
        ## x = mx gives y = 1
        ## x = 0 gives y = 0.5
        y <- 1/2*(x/mx + 1)
        rgb(pal(y), maxColorValue=255)
    }
    divRamp <- colorRamp(divPal)
    ## Diverging palette where white is associated with the interval
    ## containing the zero
    pal <- break2pal(mids, mx, divRamp)
    

    And finally levelplot displays the result:

    levelplot(SISav, par.settings=rasterTheme(region=pal),
              at=breaks, contour=TRUE)
    

    levelplot