We will see part of the ComplexHeatmap
package. It is
very huge … as you can see at https://jokergoo.github.io/ComplexHeatmap-reference/book/index.html
The ComplexHeatmap
package is inspired by the
pheatmap
package, but contains lots more functions.
We will see how to create a single heatmap, annotate it and combine heatmaps.
The basic function is Heatmap()
(remember the “H”).
library(ComplexHeatmap)
set.seed(18494)
# Let's create some data
a=rnorm(n = 15, mean = 0, sd = 1.5)
b=rnorm(n = 15, mean = 0, sd = 1.5)
c=rnorm(n = 15, mean = 0, sd = 1.5)
d=rnorm(n = 15, mean = 0, sd = 1.5)
e=rnorm(n = 15, mean = 0, sd = 1.5)
mat = cbind(a,b,c,d,e)
nr=nrow(mat)
nc=ncol(mat)
rownames(mat) = paste0("row", seq_len(nr))
colnames(mat) = paste0("column", seq_len(nc))
mat
## column1 column2 column3 column4 column5
## row1 -1.3465244 1.00936743 1.64244961 -1.5059708 0.8218742
## row2 2.0324465 -1.53864930 -0.67816605 -0.7309508 -0.4663479
## row3 -0.8861685 2.24298887 3.58247869 -0.4668248 1.3957509
## row4 2.3264709 0.59494845 -0.22488257 -2.2380533 -1.3736806
## row5 -1.3293604 2.07012406 -0.52288830 0.3878225 -0.5951234
## row6 -2.4663162 0.18830544 1.80684537 0.2605575 0.8862452
## row7 1.6711606 -2.13292014 -3.16089187 1.7503011 0.1221308
## row8 2.3750055 0.36904930 -0.75873504 -2.1066430 -0.8081975
## row9 -1.2459425 0.09876895 1.65984869 1.3861493 -1.0240513
## row10 0.8906801 1.02709999 -1.57741951 -2.2797123 -0.7204702
## row11 -1.5657081 2.52207354 0.04639403 1.3276764 -1.5855088
## row12 0.5667032 0.65457395 0.26647537 -1.1475006 -1.3251155
## row13 0.7981030 0.88466693 0.46592507 0.2284560 2.0234594
## row14 0.7155088 -0.40292172 3.20243917 1.4620738 1.9165075
## row15 1.2392599 -2.46904817 -0.39922026 0.2712318 -1.6328971
Heatmap(mat)
# remember that if you use Heatmap() function in a loop you have to assign it to a variable and then use draw()
You can customize your heatmap by choosing dimensions, removing automatic clustering on both rows and columns, changing colors, assigning it a title, changing names and so on…
library(grid)
Heatmap(mat, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"))
Heatmap(mat, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"),cluster_rows = F)
Heatmap(mat,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), cluster_columns = F)
Heatmap(mat,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), cluster_rows = F, cluster_columns = F)
Heatmap(mat, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), name = "Heatmap N.1")
Heatmap(mat,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), border = T)
Heatmap(mat,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), row_title = "Rows", column_title = "Cols")
Heatmap(mat,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"),row_split = c(rep("A", 10), rep("B", 5)),column_split = c(rep("C", 2), rep("D", 3)) )
library(circlize)
col_fun = colorRamp2(c(min(unlist(mat)), 0, max(unlist(mat))), c("green", "white", "magenta"))
Heatmap(mat, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"),col = col_fun)
# Let's create a matrix with soma missing values (NA)
mat2=mat
mat2[12,4]=NA
mat2[15,5]=NA
mat2[3,2]=NA
mat2[6,1]=NA
Heatmap(mat2,width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), col = col_fun, na_col = "black")
# There are also functions that allow to customize borders
Heatmap(mat, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"),name = "mat", rect_gp = gpar(col = "white", lwd = 2),
column_title = "Cell borders", col=col_fun)
# We can also customize titles, font, sizes etc (refer to the user guide for examples)
You can add annotations both on rows and columns.
ann_bar1=1:5
ann_bar2=sample(size = 15, x=1:100)
col_fun1 = colorRamp2(c(1,5), c("green", "orange"))
col_fun2 = colorRamp2(c(1,100), c("cyan", "pink"))
# Build the column annotation
haC = HeatmapAnnotation(
barC = anno_barplot(ann_bar1, gp = gpar(fill = col_fun1(ann_bar1))), # annotation name and values
groupC = c(rep("C", 2), rep("D", 3)),# other annotation name and values
# assign colors
col = list(
groupC = c("C" = "cornflowerblue", "D" = "yellow")
),
gp = gpar(col = "black"),
which = "column"
)
haR = HeatmapAnnotation(
barR = anno_barplot(ann_bar2, gp = gpar(fill = col_fun2(ann_bar2))), # annotation name and values
groupR = c(rep("A", 10), rep("B", 5)),# other annotation name and values
# assign colors
col = list(
groupR = c("A" = "blue", "B" = "red")
),
gp = gpar(col = "black"),
which = "row"
)
h3=Heatmap(mat, name = "mat", width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"), col=col_fun,
right_annotation = haR,
top_annotation = haC)
h3
# Notice that we "manually" coloured barplots, so legend is not inserted... insert it manually
lgd1 = Legend(col_fun = col_fun1, title = "barC")
lgd2 = Legend(col_fun = col_fun2, title = "barR")
pd = packLegend(lgd1, lgd2)
draw(h3, annotation_legend_list=pd)
If you have to plot together different heatmaps that share row names
you can assign them to variables and then use +
to combine
them.
h1=Heatmap(mat, name = "mat", rect_gp = gpar(col = "white", lwd = 2),
column_title = "Cell borders", col=col_fun, width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"))
h2=Heatmap(mat2, col = col_fun, na_col = "black", width=unit(0.5*nc, "cm"), height=unit(0.5*nr, "cm"))
h_list = h1 + h2
class(h_list)
## [1] "HeatmapList"
## attr(,"package")
## [1] "ComplexHeatmap"
# explore draw() function to see customizations
h_list
A Venn diagram shows relations between two ore more sets. In particular, it is useful if we want to see if there are terms in common between two groups. Note that with more than 3 sets, it is better to switch to an upset plot, otherwise intersections become confusing.
We will use the VennDiagram
package.
venn.diagram()
function require a list of character
vectors that represent our groups (they can be gene names, transcript
names, sample names … whatever you need)
library(VennDiagram)
# Generate 3 groups of 1000 words
group1 <- paste0(rep("word_" , 1000) , sample(c(1:100000) , 1000 , replace=F))
group2 <- paste0(rep("word_" , 1000) , sample(c(1:100000) , 1000 , replace=F))
group3 <- paste0(rep("word_" , 1000) , sample(c(1:100000) , 1000 , replace=F))
str(group1)
## chr [1:1000] "word_4544" "word_51040" "word_13966" "word_85877" ...
head(group1)
## [1] "word_4544" "word_51040" "word_13966" "word_85877" "word_47898"
## [6] "word_27259"
# Plot
venn.diagram(
x = list(group1, group2, group3),
category.names = c("Group1" , "Group2" , "Group3"),
filename = "venn_diagram.png",imagetype = "png", # possible imege types are: "png", "tiff" or "svg"
output=TRUE
)
## [1] 1
We can customize our diagram:
library(MetBrewer)
my_palette=met.brewer(name = "Klimt", n=3, type = "discrete")
venn.diagram(
x = list(group1, group2, group3),
category.names = c("Group1" , "Group2" , "Group3"),
filename = "venn_diagram_manipulated.png",
output=TRUE,
# Output features
imagetype="png" ,
height = 480 ,
width = 480 ,
resolution = 300,
# Circles
lwd = 2,
lty = 'blank',
fill = my_palette,
# Numbers
cex = .6,
fontface = "bold",
fontfamily = "sans",
# Set names
cat.cex = 0.6,
cat.fontface = "bold",
cat.default.pos = "outer",
cat.pos = c(-27, 27, 135),
cat.dist = c(0.055, 0.055, 0.085),
cat.fontfamily = "sans",
rotation = 1
)
## [1] 1
Let’s make other two groups and try to intersect them through a Venn diagram:
library(VennDiagram)
# Generate 3 groups of 1000 words
group4 <- paste0(rep("word_" , 1000) , sample(c(1:100000) , 1000 , replace=F))
group5 <- paste0(rep("word_" , 1000) , sample(c(1:100000) , 1000 , replace=F))
my_palette=met.brewer(name = "Klimt", n=5, type = "discrete")
venn.diagram(
x = list(group1, group2, group3, group4, group5),
category.names = c("G1" , "G2" , "G3", "G4", "G5"),
filename = "venn_diagram_many_groups.png",
output=TRUE,
# Output features
imagetype="png" ,
# Circles
lwd = 2,
lty = 'blank',
fill = my_palette
)
## [1] 1
It becomes difficult to distinguish intersection between all groups. We can use the upset plot:
library(UpSetR)
# Define some vectors
group1 <- paste0(rep("word_" , 400) , sample(c(1:100000) , 400 , replace=F))
group2 <- paste0(rep("word_" , 30) , sample(c(1:100000) , 30 , replace=F))
group3 <- paste0(rep("word_" , 590) , sample(c(1:100000) , 590 , replace=F))
group4 <- paste0(rep("word_" , 400) , sample(c(1:100000) , 400 , replace=F))
group5 <- paste0(rep("word_" , 300) , sample(c(1:100000) , 300 , replace=F))
group6 <- paste0(rep("word_" , 800) , sample(c(1:100000) , 800 , replace=F))
# Make a names list with vectors
group_list=list("Group1"=group1,
"Group2"=group2,
"Group3"=group3,
"Group4"=group4,
"Group5"=group5,
"Group6"=group6)
# Make the upset
upset(fromList(group_list),nsets = 6, sets.bar.color = "violet" , main.bar.color = "navyblue")
# as you can see you can customise your plot... explore parameters!!