DaniCee
DaniCee

Reputation: 3207

R: center red_to_blue color palette at 0 in levelplot

I am making a levelplot in which one variable of my data frame is used to color the cells (fold.change) and another (map.signif) is written on top. In this case, I write * and ** for significant cells.

This is my MWE:

set.seed(150)
pv.df <- data.frame(compound=rep(LETTERS[1:8], each=3), comparison=rep(c("a/b","b/c","a/c"), 8), p.value=runif(24, 0, 0.2), fold.change=runif(24, -0.3, 0.9))
pv.df$map.signif <- ifelse(pv.df$p.value > 0.05, "", ifelse(pv.df$p.value > 0.01,"*", "**"))
pv.df
myPanel <- function(x, y, z, ...) {
  panel.levelplot(x, y, z, ...)
  panel.text(x, y, pv.df$map.signif, cex=3)
}
#install.packages("latticeExtra")
library(latticeExtra)
library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(11, "RdBu"))(11)
png(filename="test.png", height=800, width=400)
print(
    levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
      pv.df,
      panel = myPanel,
      col.regions = cols,
      at = do.breaks(range(pv.df$fold.change), 11),
      colorkey = list(col = cols, 
                      at = do.breaks(range(pv.df$fold.change), 11)),
      xlab = "", ylab = "",              # remove axis titles
      scales = list(x = list(rot = 45),  # change rotation for x-axis text
                    cex = 0.8),          # change font size for x- & y-axis text
      main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
                  cex = 1.5))
)
dev.off()

Which produces:

test

My question here is: Since fold.change includes negative and positive values, how do I make 0 to coincide with white in my color palette, so negative values are in red, and positive ones in blue?

For the win, is it possible to wirte the * in black when the cell background is clear, and in white when the background is dark? Many thanks!

Upvotes: 0

Views: 2797

Answers (1)

spadarian
spadarian

Reputation: 1624

Your range is not simetrical. An alternative is this one:

max_abs <- max(abs(pv.df$fold.change))
brk <- do.breaks(c(-max_abs, max_abs), 11)
levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
          pv.df,
          panel = myPanel,
          col.regions = cols,
          at = brk,
          colorkey = list(col = cols, 
                          at = brk),
          xlab = "", ylab = "",              # remove axis titles
          scales = list(x = list(rot = 45),  # change rotation for x-axis text
                        cex = 0.8),          # change font size for x- & y-axis text
          main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
                      cex = 1.5))

enter image description here

Edit

If you don't want the extra breaks:

max_abs <- max(abs(pv.df$fold.change))
brk <- do.breaks(c(-max_abs, max_abs), 11)
first_true <- which.max(brk > min(pv.df$fold.change))
brk <- brk[(first_true -1):length(brk)]
cols <- cols[(first_true -1):length(cols)]
levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
          pv.df,
          panel = myPanel,
          col.regions = cols,
          at = brk,
          colorkey = list(col = cols, 
                          at = brk),
          xlab = "", ylab = "",              # remove axis titles
          scales = list(x = list(rot = 45),  # change rotation for x-axis text
                        cex = 0.8),          # change font size for x- & y-axis text
          main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
                      cex = 1.5))

enter image description here

Upvotes: 1

Related Questions