0

I have plotted multiple heatmaps in one layout using grid.arrange but I want to add two more features to it. I want to plot a common legend and also put a title to every individual heatmap. But I am not able to do it. If I use main = "XYZ, it throws an error.

This is the code I used. I want to use sheets name as heatmap title for the corresponding heatmap and a common legend for all (preferably as a horizontal bar at the bottom). Of course, there will be a main title at the top, like the one in my code. Is there a way to do that?

file = "I:/COMPARISON/heatmap.xlsx"

## load all sheets
sheets <- openxlsx::getSheetNames(file)
SheetList <- lapply(sheets,openxlsx::read.xlsx,xlsxFile=file)
names(SheetList) <- sheets


## create color ramp and colour breaks
col_breaks <- c(-2,-1.5,-1,0,1,1.5,2)
my_palette<-colorRampPalette(c("red4","red1","darkorange2","gold2",
                               "yellow4","yellow",
                               "chartreuse3","green4"))

#Define a new function to create Row labels
rname <- function(i){
  if (i <= 3)
    rname = format(ymd(seq(as.Date("1982-01-01"), as.Date("2017-12-01"), by = "months")), "%b-%Y")
  else
    rname = format(ymd(seq(as.Date("2021-01-01"), as.Date("2100-12-01"), by = "months")), "%b-%Y")
}

grab_grob <- function(){
  grid.echo()
  grid.grab()
}

g1 = lapply(1:6, function(i) {
  arr = as.data.frame(SheetList[i])
  heatmap.2(as.matrix(arr[2:7]),
            dendrogram ='none',
            Colv=FALSE, Rowv = FALSE, 
            key=FALSE, keysize=1.0, symkey=FALSE, density.info='none',
            trace='none',
            scale="none",cexRow=0.7,cexCol=0.9,
            breaks = col_breaks,col=my_palette,
            labRow = rname(i),
            labCol = c("spei-3", "spei-6", "spei-9", "spei-12", "spei-15", "spei-24"),
            colsep = 0:ncol(arr), sepwidth = c(0.01),
            sepcolor = c("grey")
  )

  grab_grob()
}
)


grid.newpage()
title1 = textGrob("Drought Progression Across Time Scales", gp=gpar(fontface="bold", fontsize = 18), vjust = 0.5)
grid.arrange(grobs = g1, ncol = 3, clip = TRUE, top = title1)

Edit: Use grid::grid.text to manually put labels

#Label heatmap in 2nd row
grid::grid.text(label = "Upper: 2021-2100", x = unit(0.17, "npc"), y = unit(0.42, "npc"), 
                gp = gpar(fontface = "bold"))
grid::grid.text(label = "Middle: 2021-2100", x = unit(0.5, "npc"), y = unit(0.42, "npc"), 
                gp = gpar(fontface = "bold"))
grid::grid.text(label = "Lower: 2021-2100", x = unit(0.83, "npc"), y = unit(0.42, "npc"), 
                gp = gpar(fontface = "bold"))

#Label heatmap in 1st row
grid::grid.text(label = "Upper: 1982-2017", x = unit(0.17, "npc"), y = unit(0.90, "npc"), 
                gp = gpar(fontface = "bold"))
grid::grid.text(label = "Middle: 1982-2017", x = unit(0.5, "npc"), y = unit(0.90, "npc"), 
                gp = gpar(fontface = "bold"))
grid::grid.text(label = "Lower: 1982-2017", x = unit(0.83, "npc"), y = unit(0.90, "npc"), 
                gp = gpar(fontface = "bold"))

Thanks Edit: Sorry, I missed the most important part of the question. The input data. There are 11 sheets, out of which I am plotting first six.

> sheets
 [1] "hr-up"                           "hr-mi"                           "hr-lo"                          
 [4] "fr-up"                           "fr-mi"                           "fr-lo"                          
 [7] "Severe and Extreme Drought Year" "Sheet3"                          "Drought Years"                  
[10] "Sheet1" 

Each sheet has some positive and negative values. This is the data in hr-up

> head(arr, 24)
   hr.up.Date hr.up.spei.3 hr.up.spei.6 hr.up.spei.9 hr.up.spei.12 hr.up.spei.15 hr.up.spei.24
1       29952           NA           NA           NA            NA            NA            NA
2       29983           NA           NA           NA            NA            NA            NA
3       30011    1.4130876           NA           NA            NA            NA            NA
4       30042    1.4712732           NA           NA            NA            NA            NA
5       30072    0.5564964           NA           NA            NA            NA            NA
6       30103   -1.2459968   -0.5623140           NA            NA            NA            NA
7       30133   -1.7858451   -1.4540796           NA            NA            NA            NA
8       30164   -1.0875569   -0.9654640           NA            NA            NA            NA
9       30195   -1.3201110   -1.4099878   -1.2005973            NA            NA            NA
10      30225   -0.8063094   -1.5222028   -1.3334039            NA            NA            NA
11      30256   -1.6281357   -1.4216326   -1.3572572            NA            NA            NA
12      30286   -0.7776727   -1.3805879   -1.4655774    -1.2753331            NA            NA
13      30317    0.3703999   -0.7713255   -1.4535241    -1.2633736            NA            NA
14      30348    0.1290419   -1.4367198   -1.3660294    -1.2868081            NA            NA
15      30376    0.2806614   -0.4843129   -1.2882978    -1.3826657     -1.191301            NA
16      30407    1.2569239    1.0307590   -0.4222725    -1.2912207     -1.069121            NA
17      30437    0.6828162    0.5760019   -1.2077939    -1.2987510     -1.204489            NA
18      30468   -0.6508188   -0.5750230   -0.9207008    -1.4586072     -1.558509            NA
19      30498   -1.2616172   -0.9499083   -0.9993924    -1.1904968     -1.763035            NA
20      30529   -1.0117591   -0.8607768   -0.8791052    -1.3347798     -1.565065            NA
21      30560   -1.0278092   -0.9915982   -0.9721936    -1.1852030     -1.523914            NA
22      30590   -0.5786023   -1.0784944   -0.8861200    -0.9186963     -1.094952            NA
23      30621   -0.7426414   -1.0677353   -0.9443890    -0.9816226     -1.348177            NA
24      30651    0.2466843   -0.9279672   -0.9099656    -0.8790897     -1.094521     -1.449477
Ray
  • 56
  • 1
  • 7
  • 1
    Could you please provide a minimal, reproducible example. The data should always be part of a question. That being said, I would try using `facet_grid()` – MKR Apr 26 '20 at 14:54
  • I am so sorry. I just added the data. Please have a look into it. In the meantime, I will try out ```facet_grid()```. – Ray Apr 27 '20 at 16:15

1 Answers1

0

You can post your data using dput(data). That's the easiest way to share the data and make sure that you post a reproducible example. I made up some data, but the principle should remain the same. The solution uses ggplot2. Hope that helps.

library(tidyverse)
data <- list(
  sheet1 = data.frame(
    category = c(paste0("rep_", 1:10)),
    value1 = rnorm(10),
    value2 = rnorm(10)),
  sheet2 = data.frame(
    category = c(paste0("rep_", 1:10)),
    value1 = rnorm(10),
    value2 = rnorm(10)),
  sheet3 = data.frame(
    category = c(paste0("rep_", 1:10)),
    value1 = rnorm(10),
    value2 = rnorm(10)))

data <- bind_rows(data, .id = "id") %>% 
  pivot_longer(c(-id, -category))

ggplot(data, aes(x= category, y=name)) +
  geom_tile(aes(fill = value)) + 
  facet_wrap(~id) +
  ggtitle("One title for all")+
  theme(plot.title = element_text(hjust = 0.5))

Created on 2020-04-27 by the reprex package (v0.3.0)

MKR
  • 1,620
  • 7
  • 20
  • Thank you for replying. But is there no way through without ```ggplot2```? I am not very acquainted with it. In fact, I am dreadful of ```ggplot2```. I never seem to get it right. Not even once. – Ray Apr 27 '20 at 19:13
  • I used ```grid.text``` in ```grid``` to put labels manually. It worked. – Ray Apr 30 '20 at 13:55