我以为热图只能画数值型数据,没想到离散型的也行啊

离散热图

0.需求

今天在群里看到一个非常漂亮的热图,我以为是什么奇怪的新R包画的,转了一圈发现原来还是大名鼎鼎的ComplexHeatmap丫。今天的代码都是在作者写的书基础上探索学习的,书在:https://jokergoo.github.io/ComplexHeatmap-reference/book/

这种图和普通热图的不同点:

  • 数据是离散型的,与常规的数值型热图不同。
  • 每行单独配色,颜色逐行变化
  • 左右两边都有文字
  • 划分的不同板块有格子

1.学习普通的离散型热图

以前画的热图无一例外都是连续型数值,这次是离散型数据咯,矩阵里面只有四个取值,所以就只有四个颜色。如果不指定的话,颜色就是随机的:

rm(list = ls())
library(ComplexHeatmap)
library(RColorBrewer)
library(circlize)
discrete_mat = matrix(sample(letters[1:4], 100, replace = TRUE), 10, 10)
Heatmap(t(discrete_mat), 
        column_split = discrete_mat[, 1],
        top_annotation = HeatmapAnnotation(group = discrete_mat[, 1]),
        border = T)
请忽略配色

切割、加边框、加注释这样的操作,参数还是蛮好找的。

编一个类似于上面那张图的输入数据,画画看。每一行都是有重复值的不同向量,并且向量的取值数量都是有限的。

sl = function(letter,n = sample(2:4,1),ncol = 100){
  sample(paste0(letter,1:n),ncol,replace = T)
}
table(sl("a"))
## 
## a1 a2 a3 a4 
## 21 31 25 23
dat = t(sapply(letters[1:10], sl))
rownames(dat) = LETTERS[1:10]
colnames(dat) = paste0("M",1:ncol(dat))
dat[1:4,1:4]
##   M1   M2   M3   M4  
## A "a1" "a2" "a1" "a2"
## B "b2" "b2" "b2" "b2"
## C "c1" "c1" "c1" "c2"
## D "d2" "d1" "d2" "d3"
col_group = rep(c("C1","C2","C3"),times = c(30,40,30))
row_group = rep(c("x","y"),times = c(6,4))

Heatmap(dat, name = "mat", 
        top_annotation = HeatmapAnnotation(cluster = col_group),
        left_annotation = rowAnnotation(foo1 = row_group),
        column_split = col_group,
        row_split = row_group,
        border = T,show_column_names = F)
请忽略配色

2.自定义颜色

ComplexHeatmap有一个特点,如果你不指定配色的话,每次运行相同代码出来的图配色都不一样哦,所以接下来自己定义颜色。

这里用到一个函数:colorRamp2,出自circlize包,可以根据你指定的几个颜色,生成一组渐变色。

# 主体热图的颜色
m = apply(dat,1,function(x){length(unique(x))})

col_fun = colorRamp2(breaks = seq(0, 1, length.out = 12),
                     colors = brewer.pal(12,"Set3"))
qz = sort(unique(as.character(dat)));length(qz)
## [1] 28
colors = col_fun(seq(0, 1, length.out = length(qz)))
names(colors) = qz
head(colors)
##          a1          a2          b1          b2          b3          c1 
## "#8DD3C7FF" "#BFE5BFFF" "#ECF7B7FF" "#F2EFBDFF" "#D8D3CDFF" "#C2B8D6FF"
# 注释条的颜色
color_an = brewer.pal(length(unique(col_group)),"Dark2")
names(color_an) = unique(col_group)
color_an
##        C1        C2        C3 
## "#1B9E77" "#D95F02" "#7570B3"
#顶部注释
top_annotation = HeatmapAnnotation(cluster = col_group,col = list(cluster = color_an),show_legend = F,show_annotation_name = F)

f = Heatmap(dat, col = colors,
        top_annotation = top_annotation,
        row_split = ifelse(row_group=="x",""," "), #这一句是为了隐藏行分组的名字
        column_split = col_group,
        show_heatmap_legend = F,
        border = T,show_column_names = F,row_names_side = "left",
        right_annotation = rowAnnotation(score = anno_text(1:nrow(dat)))
        )
f
隐藏图例了

3.自定义图例

前面有个参数是show_heatmap_legend = Fshow_legend = F,是不显示主体与注释图例的意思。这里之所以不显示是为了自定义图例。否则呢,主体热图的图例就会全部放在一起,不能按行来显示哦。

# 主体热图的图例
k = 1
lgd = list()
for(i in 1:10){
  un = sort(unique(dat[i,]))
  ti = rownames(dat)[i]
  lgd[[i]] = Legend(seq(0, 1, length.out = length(un)), labels = un,
               title = ti, legend_gp = gpar(fill =colors[k:(k+length(un)-1)]))
  k = k + length(un)
}
# 注释的图例
cld = Legend(labels = c("a1","a2","a3"), title = "cluster", 
        legend_gp = gpar(fill = color_an))

# 把各个图例合并在一起
p = packLegend(list = c(cld,lgd),
               direction = "horizontal",gap = unit(0.6, "cm"))

draw(p)
全部的图例哦
# 主体和图例画到一起
draw(f,heatmap_legend_list = p,heatmap_legend_side = "bottom")
收工
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容