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(...)
}
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(...)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With