9

Let's say:

m1<-matrix(rnorm(1000),ncol=100)

and defining colours:

cols = colorRampPalette(c("white", "red"))(30)

I am producing a heatmap without clustering with pheatmap function:

pheatmap(dist(t(m1)), cluster_rows = F, cluster_cols = F, show_rownames = TRUE, 
color = cols, main = 'Heatmap')

the question is, how can I define colours in order to get the same heatmap but only with pixels of specific value coloured (for example less than 0.1).

I tried to set

cols = ifelse(dist(t(m1))<0.1,'red','black')

but didn't work.

Kwnwps
  • 353
  • 1
  • 4
  • 15

2 Answers2

15

For a simple binary color scheme, you can use the breaks argument:

library(pheatmap)

set.seed(1)
m1<-matrix(c(rnorm(1000)), ncol=100)

pheatmap(dist(t(m1)),
         cluster_rows = F,
         cluster_cols = F,
         show_rownames = TRUE, 
         color = c("red", "black"),
         breaks = c(0, 3, 9),  # distances 0 to 3 are red, 3 to 9 black
         main = 'Heatmap')

It looks like this:

enter image description here

If you prefer color gradients, it can be done as follows:

m <- matrix(c(rnorm(1000)), ncol=100)
distmat <- dist(t(m))

# Returns a vector of 'num.colors.in.palette'+1 colors. The first 'cutoff.fraction'
# fraction of the palette interpolates between colors[1] and colors[2], the remainder
# between colors[3] and colors[4]. 'num.colors.in.palette' must be sufficiently large
# to get smooth color gradients.
makeColorRampPalette <- function(colors, cutoff.fraction, num.colors.in.palette)
{
  stopifnot(length(colors) == 4)
  ramp1 <- colorRampPalette(colors[1:2])(num.colors.in.palette * cutoff.fraction)
  ramp2 <- colorRampPalette(colors[3:4])(num.colors.in.palette * (1 - cutoff.fraction))
  return(c(ramp1, ramp2))
}

cutoff.distance <- 3  
cols <- makeColorRampPalette(c("white", "red",    # distances 0 to 3 colored from white to red
                               "green", "black"), # distances 3 to max(distmat) colored from green to black
                             cutoff.distance / max(distmat),
                             100)

pheatmap(distmat,
         cluster_rows = F,
         cluster_cols = F,
         show_rownames = TRUE, 
         color = cols,
         main = 'Heatmap')

Which then looks like this:

enter image description here

WhiteViking
  • 3,146
  • 1
  • 19
  • 22
  • Hi @WhiteViking, I tried this and it was processing for more than half an hour until I stopped it. I'm working with Rstudio in a McBook 1,4 GHz Intel Core i5. Also, it's not bad for me to only have red dots in black background. – Kwnwps Sep 13 '15 at 11:54
  • @Kwnwps I've added an example using a binary color scheme (red dots on black). – WhiteViking Sep 13 '15 at 13:55
  • @Kwnwps As for the long processing time: does that happen for this toy example? Or only for a much bigger dataset - if so what size is it? – WhiteViking Sep 13 '15 at 13:57
  • Thanks. I tried it in a 230 x 230 distance matrix. The toy example didn't had any problems. The optimal for my case will be a combination, meaning black until a threshold and then gradually going from a colour to another. – Kwnwps Sep 13 '15 at 14:34
  • I can't explain why it would take that long. In my example above with the smooth color gradients, a test where `m <- matrix(c(rnorm(230*1000)), ncol=230)`, calculating `dist(t(m))` and displaying the `pheatmap` takes only a few seconds on my 2.3 GHz i5 MacBook Pro with 8GB RAM. – WhiteViking Sep 13 '15 at 16:29
  • yes it doesn't make sense, I need to search it up a bit. I think your code is fine. – Kwnwps Sep 13 '15 at 22:50
  • Hey again, do you know how I can get rid of the white lines that separate each pixel? It's a bit annoying for the eye.. – Kwnwps Sep 19 '15 at 10:32
  • 1
    Pass `border_color = NA` as an additional argument to pheatmap. (See `?pheatmap`...) – WhiteViking Sep 19 '15 at 10:47
  • Damn, it was a silly typo, I was misspelling the command.. sorry about that. – Kwnwps Sep 19 '15 at 11:10
3

Not what you asked for but here's a ggplot solution that may help someone else.

set.seed(1)         # for reproducible example
m1 <- matrix(rnorm(1000),ncol=100)
d  <- dist(t(m1))

library(ggplot2)
library(reshape2)   # for melt(...)
gg.df <- melt(as.matrix(d), varnames=c("row","col"))

# fill is red for value < 3; black for value >= 3
ggplot(gg.df, aes(x=factor(col), y=factor(row)))+ 
  geom_tile(aes(fill=ifelse(value<3, "below", "above")), color=NA)+
  scale_fill_manual("Threshold",values=c(below="#FF0000", above="#000000"))+
  coord_fixed()

# fill is black for value > 3; gradient white to red for value <= 3
ggplot(gg.df, aes(x=factor(col), y=factor(row)))+ 
  geom_tile(aes(fill=value), color=NA)+
  scale_fill_gradient(low="#FFFFFF", high="#FF0000", limits=c(0,3), na.value="black")+
  coord_fixed()

jlhoward
  • 58,004
  • 7
  • 97
  • 140