pheatmap: Color for NA

前端 未结 5 1703
梦谈多话
梦谈多话 2021-02-05 17:41

Using R package pheatmap to draw heatmaps. Is there a way to assign a color to NAs in the input matrix? It seems NA gets colored in white by default. E.g.:

libra         


        
相关标签:
5条回答
  • 2021-02-05 18:16

    It is possible, but requires some hacking.

    First of all let's see how pheatmap draws a heatmap. You can check that just by typing pheatmap in the console and scrolling through the output, or alternatively using edit(pheatmap).

    You will find that colours are mapped using

    mat = scale_colours(mat, col = color, breaks = breaks)
    

    The scale_colours function seems to be an internal function of the pheatmap package, but we can check the source code using

    getAnywhere(scale_colours)
    

    Which gives

    function (mat, col = rainbow(10), breaks = NA) 
    {
        mat = as.matrix(mat)
        return(matrix(scale_vec_colours(as.vector(mat), col = col, 
            breaks = breaks), nrow(mat), ncol(mat), dimnames = list(rownames(mat), 
            colnames(mat))))
    }
    

    Now we need to check scale_vec_colours, that turns out to be:

    function (x, col = rainbow(10), breaks = NA) 
    {
        return(col[as.numeric(cut(x, breaks = breaks, include.lowest = T))])
    }
    

    So, essentially, pheatmap is using cut to decide which colours to use.

    Let's try and see what cut does if there are NAs around:

    as.numeric(cut(c(1:100, NA, NA), seq(0, 100, 10)))
      [1]  1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3
     [29]  3  3  4  4  4  4  4  4  4  4  4  4  5  5  5  5  5  5  5  5  5  5  6  6  6  6  6  6
     [57]  6  6  6  6  7  7  7  7  7  7  7  7  7  7  8  8  8  8  8  8  8  8  8  8  9  9  9  9
     [85]  9  9  9  9  9  9 10 10 10 10 10 10 10 10 10 10 NA NA
    

    It returns NA! So, here's your issue!

    Now, how do we get around it? The easiest thing is to let pheatmap draw the heatmap, then overplot the NA values as we like.

    Looking again at the pheatmap function you'll see it uses the grid package for plotting (see also this question: R - How do I add lines and text to pheatmap?)

    So you can use grid.rect to add rectangles to the NA positions. What I would do is find the coordinates of the heatmap border by trial and error, then work from there to plot the rectangles.

    For instance:

    library(pheatmap)
    m<- matrix(c(1:100), nrow= 10)
    m[1,1]<- NA
    m[10,10]<- NA
    
    hmap <- pheatmap(m, cluster_rows=FALSE, cluster_cols=FALSE)
    # These values were found by trial and error
    # They WILL be different on your system and will vary when you change
    # the size of the output, you may want to take that into account.
    min.x <- 0.005
    min.y <- 0.01
    max.x <- 0.968
    max.y <- 0.990
    width <- 0.095
    height <- 0.095
    
    coord.x <- seq(min.x, max.x-width, length.out=ncol(m))
    coord.y <- seq(max.y-height, min.y, length.out=nrow(m))
    
    for (x in seq_along(coord.x))
      {
      for (y in seq_along(coord.y))
        {
        if (is.na(m[x,y]))
            grid.rect(coord.x[x], coord.y[y], just=c("left", "bottom"),
                      width, height, gp = gpar(fill = "green"))    
        }
      }
    

    A better solution would be to hack the code of pheatmap using the edit function and have it deal with NAs as you wish...

    0 讨论(0)
  • 2021-02-05 18:23

    Actually, the question is easy now. The current pheatmap function has incorporated a parameter for assigning a color to "NA", na_col. Example:

    na_col = "grey90"
    
    0 讨论(0)
  • 2021-02-05 18:28

    If you want the NAs to be grey, you can simply force the "NA" as double.

    m[is.na(m)] <- as.double("NA")
    pheatmap(m, cluster_rows=F, cluster_cols=F)
    
    0 讨论(0)
  • 2021-02-05 18:31

    You can enable assigning a colour by using the developer version of pheatmap from github. You can do this using devtools:

    #this part loads the dev pheatmap package from github
    if (!require("devtools")) {
      install.packages("devtools", dependencies = TRUE)
      library(devtools)
    }
    install_github("raivokolde/pheatmap")
    

    Now you can use the parameter "na_col" in the pheatmap function:

    pheatmap(..., na_col = "grey", ...)
    

    (edit) Don't forget to load it afterwards. Once it is installed, you can treat it as any other installed package.

    0 讨论(0)
  • 2021-02-05 18:35

    If you don't mind using heatmap.2 from gplots instead, there's a convenient na.color argument. Taking the example data m from above:

    library(gplots)
    heatmap.2(m, Rowv = F, Colv = F, trace = "none", na.color = "Green")
    
    0 讨论(0)
提交回复
热议问题