Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign a specific color to NA in an image plot

Tags:

r

I am using the image command to plot a matrix, the matrix contains some NA values. I am using image like

image(figData, zlim = zRange, col = colors, useRaster=TRUE)

zRange is smaller than the actual range of the figData. I am using the top colormap in the following group, which is compatible with red-green color perception deficiencies:

http://www.mathworks.com/matlabcentral/fx_files/31761/6/thumbnail_184481.jpg

I want to select a specific color for NA values in figData that is outside colors (for example, gray). NA values are being mapped now to the last element of colors (white) and therefore I can't distinguish them from out of range values.

Ideally I would like a solution that works no matter which color palette I am using.

I want something similar to the na.color option in heatmap.2, how can I do it? I am willing to modify the image source code to accomplish this, but image seems to call the rasterImage function whose source code I can't find.


After accepting Jealie's answer I am including here the code to account differently for values below and above the range:

image.nan <- function(z,  zlim, col, na.color='gray', outside.below.color='black', outside.above.color='white',...)
{
  zstep <- (zlim[2] - zlim[1]) / length(col); # step in the color palette
  newz.below.outside <- zlim[1] - zstep # new z for values below zlim
  newz.above.outside <- zlim[2] + zstep # new z for values above zlim
  newz.na <- zlim[2] + 2 * zstep # new z for NA

  z[which(z<zlim[1])] <- newz.below.outside # we affect newz.below.outside
  z[which(z>zlim[2])] <- newz.above.outside # we affect newz.above.outside
  z[which(is.na(z>zlim[2]))] <- newz.na # same for newz.na

  zlim[1] <- zlim[1] - zstep # extend lower limit to include below value
  zlim[2] <- zlim[2] + 2 * zstep # extend top limit to include the two new values above and na

  col <- c(outside.below.color, col, outside.above.color, na.color) # we construct the new color range by including: na.color and na.outside

  image(z=z,  zlim=zlim, col=col, ...) # we finally call image(...)
}
like image 902
nesuribe Avatar asked Jan 07 '14 16:01

nesuribe


1 Answers

Small correction: values outside are not being mapped to the last element of col, but they are instead not being plotted at all (and no color looks white..).

Otherwise, to answer your question, the simplest way is to write a wrapper around image, with two new arguments: na.color and outside.color. Here is my suggestion, which defaults to gray for NA values and white for values outside zlim:

my.image <- function(figData,  zlim, col, na.color='gray', outside.color='white', ...)
{
  newz.na <- zlim[2]+(zlim[2]-zlim[1])/length(col) # new z for NA
  newz.outside <- zlim[2]+2*(zlim[2]-zlim[1])/length(col) # new z for values outside zlim

  figData$z[which(is.na(figData$z>zlim[2]))] <- newz.na # we affect newz.outside
  figData$z[which(figData$z<zlim[1] | figData$z>zlim[2])] <- newz.outside # same for newz.na


  zlim[2] <- zlim[2]+2*(zlim[2]-zlim[1])/length(col) # we finally extend the z limits to include the two new values 

  col <- c(col, na.color, outside.color) # we construct the new color range by including: na.color and outside.color

  image(figData,  zlim=zlim, col=col, ...) # we finally call image(...)
}
like image 109
Jealie Avatar answered Sep 27 '22 17:09

Jealie