Search code examples
rpositionalignmentelementheatmap

Difficulty positioning heatmap.2 components


I have been really struggling to position the components of my heatmap.2 output.

I found this old answer explaining how the element positioning worked from @IanSudbery which seemed really clear and I thought it had given me the understanding I need, but I'm still not grasping something.

I understand that the elements are all essentially put in a lattice of windows but they aren't behaving in a way I understand.

Here is my code and the current output (at the very bottom is the bit of interest which orders the figure elements):

for(i in 1:length(ConditionsAbbr)) {

# creates its own colour palette 
    my_palette <- colorRampPalette(c("snow", "yellow", "darkorange", "red"))(n = 399)

  # (optional) defines the colour breaks manually for a "skewed" colour transition
    col_breaks = c(seq(0,0.09,length=100),    #white 'snow'
                 seq(0.1,0.19,length=100), # for yellow
                 seq(0.2,0.29,length=100), # for orange 'darkorange'
                 seq(0.3,1,length=100))    # for red

  # creates a 5 x 5 inch image
  png(paste(SourceDir, "Heatmap_", ConditionsAbbr[i], "XYZ.png"),    # create PNG for the heat map        
      width = 5*600,        # 5 x 600 pixels
      height = 5*600,
      res = 300,            # 300 pixels per inch
      pointsize = 8)        # smaller font size

  heatmap.2(ConditionsMtx[[ConditionsAbbr[i]]],
            cellnote = ConditionsMtx[[ConditionsAbbr[i]]],  # same data set for cell labels
            main =  paste(ConditionsAbbr[i], "XYZ"), # heat map title
            notecol="black",      # change font color of cell labels to black
            density.info="none",  # turns off density plot inside color legend
            trace="none",         # turns off trace lines inside the heat map
            margins =c(12,9),     # widens margins around plot
            col=my_palette,       # use on color palette defined earlier
            breaks=col_breaks,    # enable color transition at specified limits
            dendrogram="none",     # No dendogram
            srtCol = 0 ,        #correct angle of label numbers
            asp = 1 ,         #this overrides layout methinks and for some reason makes it square
            adjCol = c(NA, -35) ,
            adjRow = c(53, NA) ,
            keysize =  1.2 ,
            Colv = FALSE ,      #turn off column clustering
            Rowv =  FALSE ,    # turn off row clustering
            key.xlab = paste("Correlation") ,
            lmat = rbind( c(0, 3), c(2,1), c(0,4) ), 
            lhei = c(0.9, 4, 0.5) )

  dev.off()               # close the PNG device


}

This gives: enter image description here

As you can see, the key is right of the matrix, there are huge amounts of white space between the matrix, the title above and key below, and it's not even as if the title and matrix are centred in the PNG?

I think to myself "well I'll just create a 3x3 that is easy to understand and edit" e.g.

        |        |
        |        |  (3)
        |        |      
--------------------------
        |  (1)   |
   (2)  | Matrix |  
        |        | 
--------------------------   
        |  (4)   |
        |  Key   |
        |        | 

And then I can get rid of the white space so it's more like this.

        |        |(3)      
    ------------------
        |  (1)   |
     (2)| Matrix |  
        |        | 
    ------------------   
        |(4) Key |

I do this using:

lmat = rbind( c(0, 0, 3), c(2, 1, 0), c(0, 4, 0) ), 
            lhei = c(0.9, 4, 0.5) ,
            lwid = c(1, 4, 1))

This is what it looks like: enter image description here

As great as it is to see my matrix in the centre, my key is still aligned to the right of my matrix and my title is taking the Silk Road East? Not to mention all the excess white space?

How do I get these to align and to all move together so the figure components fit snugly together?

EDIT: reducing my margins helped to reduce the whitespace but it's still excessive.


Solution

  • Here are the final changes I made to get my results, however, I would recommend using the advice of Maurits Evers if you aren't too invested in heatmap.2. Don't overlook the changes I made to the image dimensions.

    # creates my own colour palette
        my_palette <- colorRampPalette(c("snow", "yellow", "darkorange", "red"))(n = 399)
    
      # (optional) defines the colour breaks manually for a "skewed" colour transition
        col_breaks = c(seq(0,0.09,length=100),    #white 'snow'
                     seq(0.1,0.19,length=100), # for yellow
                     seq(0.2,0.29,length=100), # for orange 'darkorange'
                     seq(0.3,1,length=100))    # for red
    
      # creates an image
      png(paste(SourceDir, "Heatmap_XYZ.png" )
    
      # create PNG for the heat map        
          width = 5*580,        # 5 x 580 pixels
          height = 5*420,       # 5 x 420 pixels
          res = 300,            # 300 pixels per inch
          pointsize =11)        # smaller font size
    
      heatmap.2(ConditionsMtx[[ConditionsAbbr[i]]],
                cellnote = ConditionsMtx[[ConditionsAbbr[i]]],  # same data set for cell labels
                main =  "XYZ", # heat map title
                notecol="black",      # change font color of cell labels to black
                density.info="none",  # turns off density plot inside color legend
                trace="none",         # turns off trace lines inside the heat map
                margins=c(0,0),     # widens margins around plot
                col=my_palette,       # use on color palette defined earlier
                breaks=col_breaks,    # enable color transition at specified limits
                dendrogram="none",     # only draw a row dendrogram
                srtCol = 0 ,        #correct angle of label numbers
                asp = 1 ,         #this overrides layout methinks and for some reason makes it square
                adjCol = c(NA, -38.3) , #shift column labels
                adjRow = c(77.5, NA) , #shift row labels
                keysize =  2 ,  #alter key size
                Colv = FALSE ,      #turn off column clustering
                Rowv =  FALSE ,    # turn off row clustering
                key.xlab = paste("Correlation") , #add label to key 
                cexRow = (1.8) , # alter row label font size
                cexCol = (1.8) , # alter column label font size
                notecex = (1.5) , # Alter cell font size
                lmat = rbind( c(0, 3, 0), c(2, 1, 0), c(0, 4, 0) ) , 
                lhei = c(0.43, 2.6, 0.6) , # Alter dimensions of display array cell heighs
                lwid = c(0.6, 4, 0.6) , # Alter dimensions of display array cell widths
                key.par=list(mar=c(4.5,0, 1.8,0) ) ) #tweak specific key paramters
    
      dev.off()
    

    Here is the output, which I will continue to refine until all spacing and font sizes suit my aesthetic preference. I would tell you exactly what I've done but I'm not 100% sure, frankly it all feels like it's held together with old gum and bailer twine, but don't kick a gift horse in the code, as they say.

    Output with improved spacing