Skip to content

levelplot + cut() for custom color palette

2 messages · Alex Reynolds

#
I have the following data as input, from which I would like to make a lattice levelplot:

-----------------
     x     y     level
1 m3134 m3134 1.0000000
2 m3134 m416B 0.4189057
3 m416B m3134 0.2696508
4 m3134  mA20 0.3322170
5  mA20 m3134 0.2454191
6 m3134    mB 0.3176792 
...                                                     
-----------------

I transform the levels as follows, so that levels are in the range [0,100]:

-----------------
     x     y level                                                                                                                                                                                                                          
1 m3134 m3134   100
2 m3134 m416B    42
3 m416B m3134    27
4 m3134  mA20    33
5  mA20 m3134    25
6 m3134    mB    32
...
-----------------

I want to create a custom color palette with the following groups, based on the levels in my input data frame mostly being between 10 and 80:

level range -- color
-----------------
[0,10) -- white
[10, 11) -- white
[11, 12) -- a mix of mostly white and a little red
...
[78,79) -- a mix of mostly red and a little white
[79,80) -- red
[80, Inf) -- black

In other words, I want to color any cell with the level of 100 (or greater than 80) with black, and any cell with a level between 0 and 80 with a color between white and red.

Here is my code:
-----------------
#! /foo/bar/bin/Rscript --vanilla
args <- commandArgs(TRUE)
dfFn <- args[1]
pdfFn <- args[2]

df <- read.table(dfFn, col.names=c("x", "y", "level"))                                                                                                                                                                           
df$level <- round(df$level*100, 0)

col.seq <- seq(10, 79, 1)
cuts <- cut(df$level, breaks = c(0, 1, seq(10, 79, 1), 80, Inf))
colors <- colorRampPalette(c('white', 'red'))(length(col.seq)+1)
levels(colors) <- c("white", cuts, "black")

library(lattice)
trellis.device(dev=pdf, file=pdfFn)
fig <- levelplot(level~x*y,
                data=df,
                col.regions=colors
                )
print(fig)
graphics.off();
-----------------

This makes a levelplot, but the coloring is incorrect. The cells in the figure are colored from white to red, for levels between 0 and 100, instead of between levels 10 and 79. The cells containing a level of 100 are painted red, instead of black.

I also get the following warning, which comes from the levels(colors) statement:

-----------------
Warning message:                                                                                                                                                                                                                             
In `levels<-`(`*tmp*`, value = c("white", "63", "24", "9", "15",  :                                                                                                                                                                          
 duplicated levels will not be allowed in factors anymore 
-----------------

What am I doing wrong with the cut() and color palette generation steps (and how can I fix them) in order to make the levelplot with correct cell coloring? Thanks for any constructive advice.

Regards,
Alex
5 days later
#
I am creating a levelplot figure with the following code. This should be repeatable code, which includes a link to the data I am working with.

---------------------------
pdfFn <- "foo.pdf"
df <- read.table("http://dl.dropbox.com/u/31495717/stackoverflow.overlaps.list.txt", sep="\t", header=FALSE)
names(df) <- c("x", "y", "level")
df$level <- round(df$level*100, 0)

# reorder cell type row-factors (in reverse of given order)
df$y <- factor(df$y, levels=unique(df$y[length(df$y):1]))

lowestValue <- min(df$level)
secondHighestValue <- unique(sort(df$level, decreasing=TRUE))[2]

numberOfColorBins <- 10
col.seq <- seq(lowestValue, secondHighestValue, length.out=numberOfColorBins)
brks <- c(0, col.seq, Inf)
cuts <- cut(df$level, breaks=brks)
colors <- colorRampPalette(c("white", "red"))(length(levels(cuts))-1)
colors <- c(colors, "black")

cls <- rep(colors, times=table(cuts))

library(lattice)
trellis.device(dev=pdf, file=pdfFn)
fig <- levelplot(cuts~x*y,
                 data=df,
                 cuts=numberOfColorBins,
                 col.regions=cls,
                 xlab="",
                 ylab="",
                 aspect="iso",
                 scales=list(
                   x=list(rot=90)
                   ),
                 panel=function(...) {
                   arg <- list(...)
                   panel.levelplot(...)
                   panel.text(df$x, df$y, df$level, cex=0.5)
                 },
                 colorkey=list(col=colorRampPalette(c("white", "red"))(length(col.seq)), at=col.seq)
                 )
print(fig)
graphics.off()
---------------------------

For reference, here is what the graph ("foo.pdf") looks like:

* http://twitpic.com/7z9u2c

Please note, in this example, the diagonal of black cells (representing cells with a level of "100").

The variable 'numberOfColorBins' defines the number of gradients between white and red, for values between the minimum level, and the second-highest level.

If I adjust the variable 'numberOfColorBins' from the current 10 to some value 16 or greater, then the diagonal of black cells (values of "100") turns into a diagonal of red cells. 

Because I define red cells as between (in this example) the minimum of "14" and the second-highest maximum "79", values of "100" should always be black. 

My question is:

If I have 16 or more color bins between white and red, inclusive, then cells that were colored black are now colored red, which is incorrect. How can I increase the number of color bins between white and red, while keeping black cells black?

Thanks for any advice.

Regards,
Alex