rcolors

Why is the color in the image not correctly set?


I expect "1" to be white, but it is red:

Xmat <- matrix(c(rep(1, 20), c(-10:9)+0.01), ncol = 2, byrow = FALSE)
dataVals <- sort(unique(as.numeric(Xmat)))
vals <- dataVals # seq(0, max(dataVals), min(diff(dataVals)))
ncolorlevels <- length(vals)

mypalette <- colorRampPalette(
  c("#006837", "#f0df0b", "#f20b0b", "#000099"))(ncolorlevels)
names(mypalette) <- vals
mypalette
ind <- which(names(mypalette) == "1")
mypalette[ind] <- "#FFFFFF"
mypalette
image(t(Xmat), col = mypalette, xlab = "Columns", ylab = "Rows", xaxt = "n", yaxt = "n")

Why?

If I use Xmat <- matrix(c(rep(1, 20), c(-10:9)), ncol = 2, byrow = FALSE) without +0.01 everything is fine. mypalettelooks fine to me:

mypalette
...    1      ...
... "#FFFFFF" ...

Concerning encoding - perhaps not the problem:

Xmat[1, 1] == as.integer(names(mypalette)[ind])
[1] TRUE # correct
all.equal(Xmat[1, 1], as.integer(names(mypalette)[ind]))
[1] TRUE # correct
Xmat == 1 # all correct
     [,1]  [,2]
[1,] TRUE FALSE 
[2,] TRUE FALSE 
[3,] TRUE FALSE
 ...

Solution

  • Better use breaks, since image() rather uses numerical binning instead of assigning colors based on their names or exact values. Something like this, so 1 falls within the white bin:

    > mids <- head(vals, -1) + diff(vals)/2
    > (breaks <- c(vals[1] - 0.5, mids, tail(vals, 1) + 0.5))
     [1] -10.490  -9.490  -8.490  -7.490  -6.490  -5.490  -4.490  -3.490
     [9]  -2.490  -1.490  -0.490   0.505   1.005   1.510   2.510   3.510
    [17]   4.510   5.510   6.510   7.510   8.510   9.510
    
    >
    > par(mar=c(3, 3, 2, 2))
    > image(t(Xmat), col=mypal, breaks=breaks)
    

    enter image description here


    Data:

    > Xmat <- matrix(c(rep(1, 20), c(-10:9) + 0.01), ncol=2, byrow=FALSE)
    > 
    > vals <- sort(unique(as.vector(Xmat)))
    > mypal <- colorRampPalette(
    +   c("#006837", "#f0df0b", "#f20b0b", "#000099"))(length(vals)) |> 
    +   setNames(vals)
    > mypal['1'] <- '#FFFFFF'