R 数据可视化 —— 聚类热图 pheatmap

前言

在前面的章节中,我们介绍了如何使用 ggplot2 绘制热图

ggplot2 绘制热图的方式很多,如 geom_rastergeom_tile

但通常仅仅绘制热图是不够的,还需要对数据进行聚类,即绘制聚类热图。

例如,最常用的就是将差异基因的表达值绘制聚类热图,来查看基因在不同样本中的表达差异情况,或者比较不同聚类分组之间的差异。

绘制聚类热图的包有很多,我们主要介绍 pheatmapComplexHeatmap

简单示例

假设我们有如下数据

> df <- read.csv("~/Downloads/RPKM_DEG.csv", row.names = 1)
> df
       control1 control2 control3   treat1   treat2   treat3
Gene1   178.413  180.616  111.951   44.264   44.251   35.842
Gene2  1790.491   33.799 3076.195  533.618  527.694  493.286
Gene3    55.313   72.512   42.625   26.291   31.324   26.485
Gene4   138.170   10.234  168.461 1014.917  968.487 1013.409
Gene5   400.783  417.081  422.252   16.958   21.532   18.350
Gene6    16.466   10.856   17.788  117.155  113.056  117.383
Gene7   282.103  484.187  192.498   73.769   68.207   72.967
...

要绘制简单的热图,可以使用内置的 heatmap 函数

heatmap(as.matrix(df))

更改颜色,并为列添加列样本的分类颜色条

heatmap(as.matrix(df), col = rainbow(10)[3:9], ColSideColors = rep(c("pink", "purple"), each = 3))

内置函数提供的样式较少,无法对某些图形属性进行设置。

所以下面我们使用 pheatmap 包来绘制热图

pheatmap

pheatmap 对图形属性提供了更精细的控制

1. 安装导入

install.packages("pheatmap")

library(pheatmap)

2. 简单示例

pheatmap(df)

这样看起来怪怪的,应该是基因的表达量差异,所以对行进行标准化

pheatmap(df, scale = "row")

嗯,一下子就顺眼多了,实验组和对照组的基因表达量差别明显

3. 聚类

默认情况下,会对数据的行列分别进行层次聚类,如果我们想在进行层次聚类之前,先对行特征,也就是基因进行 k-means 聚类,我们可以

pheatmap(df, scale = "row", kmeans_k = 3)
k-均值聚类

先将基因聚为 3 类,再进行层次聚类

如果只想对其中行列中的一个进行聚类,可以使用 cluster_rowscluster_cols 参数,取消对行或列的距离

pheatmap(df, scale = "row", cluster_rows = FALSE)

默认的距离度量为欧氏距离,也可以分别为行列指定不同的距离度量,例如

pheatmap(df, scale = "row", clustering_distance_rows = "correlation", clustering_distance_cols = "manhattan")

也可以使用 clustering_method 参数来指定不同的聚类方法,支持以下几种方法:

'ward', 'ward.D', 'ward.D2', 
'single', 'complete', 'average', 
'mcquitty', 'median', 'centroid'
pheatmap(df, scale = "row", clustering_method = "ward.D")

4. 图例

图例的设置很简单,即通过 legend_breaks 参数设置断点,legend_labels 参数设置断点处的标签

pheatmap(df, scale = "row", legend_breaks = c(-1, 0, 1), legend_labels = c("low", "median", "high"))

如果不想显示图例,直接设置 legend = F 就行

5. 边框

设置边框颜色

pheatmap(df, scale = "row", border_color = "white")

删除边框

pheatmap(df, scale = "row", border = F)

6. 单元格

默认情况下,单元格的长度和宽度会根据图片的大小自动调整,如果想固定单元格的大小,可以使用 cellwidthcellheight 两个参数

pheatmap(df, scale = "row", cellwidth = 15, cellheight = 15)

如果我们想在单元格中显示对于的数值,可以设置 display_numbers = TRUE

pheatmap(df, scale = "row", display_numbers = TRUE)

对显示的数值进行格式化

pheatmap(
  df,
  scale = "row",
  display_numbers = TRUE,
  # 显示为科学计数法
  number_format = "%.1e",
  # 设置颜色
  number_color = "#4daf4a",
  # 设置数值字体大小
  fontsize_number = 10
)

或者,为 display_numbers 参数传递一个矩阵

例如,根据表达值是否大于 100 来显示不同的标记

pheatmap(
  df, scale = "row", 
  display_numbers = matrix(ifelse(df > 100, "+", "-"), nrow = nrow(df)), 
  number_color = "#4daf4a", 
  fontsize_number = 10
)

7. 分块

在不对数据进行聚类的情况下,可以对行列进行自定义划分为不同的块

pheatmap(
  df,
  scale = "row",
  cluster_rows = FALSE,
  cluster_cols = FALSE,
  gaps_col = 3,
  gaps_row = c(8, 9),
  border_color = "black"
)

或者只对行或列进行分块

pheatmap(
  df,
  scale = "row",
  cluster_rows = FALSE,
  gaps_row = c(8, 12, 16),
  border_color = "black"
)

总之,只能对未聚类的行或列进行分块

或者,根据层次聚类的结果,对数据进行分块

pheatmap(
  df,
  scale = "row",
  cutree_rows = 3,
  cutree_cols = 2
)

8. 标签

使用 main 参数来设置图像的标题

pheatmap(
  df, scale = "row", 
  main = "title"
)

可以使用 show_colnamesshow_rownames 不显示标签

pheatmap(
  df, scale = "row", 
  show_colnames = FALSE,
  show_rownames = FALSE
)

分别设置标签的大小,同时设置列标签的倾斜角度,可选的角度有 270、0、45、90、315

pheatmap(
  df, scale = "row", 
  fontsize_row = 8,
  fontsize_col = 12,
  angle_col = 45
)

也可以使用 fontsize 参数统一行列标签的大小

也可以自定义行列标签

pheatmap(
  df, scale = "row", 
  labels_row = paste0("Gene", LETTERS[1:20]),
  labels_col = rep(c("Cancer", "Noraml"), each = 3)
)

9. 注释

我们可以分别为行和列构建分组信息,例如对于行是基因,可以将其分为癌基因和抑癌基因等,而列为样本可以分为癌症和配对正常样本,同时样本对应的患者应该会有年龄性别等信息

例如

# 行注释信息
annotation_row <- data.frame(
  GeneClass = sample(c("oncogene", "tumor suppressor"), size = 20, replace = TRUE)
)
rownames(annotation_row) <- paste0("Gene", 1:20)
# 列注释信息
annotation_col <- data.frame(
  type = rep(c("Noraml", "Cancer"), each = 3),
  Age = sample(30:60, 6)
)
rownames(annotation_col) <- colnames(df)

我们可以将这些信息以颜色条的方式添加到图中

pheatmap(
  df,
  scale = "row",
  color = rainbow(7),
  annotation_row = annotation_row,
  annotation_col = annotation_col
)

隐藏图例

pheatmap(
  df,
  scale = "row",
  color = rainbow(7),
  annotation_row = annotation_row,
  annotation_col = annotation_col,
  legend = FALSE,
  angle_col = 45,
)

10. 对象信息

我们可以回去 pheatmap 函数返回的对象的信息

> p <- pheatmap(df, scale = "row")
> summary(p)
         Length Class  Mode   
tree_row 7      hclust list   
tree_col 7      hclust list   
kmeans   1      -none- logical
gtable   6      gtable list 

可以看到,返回对象 p 中包含 4 个变量,我们可以根据 tree_rowtree_col 提取出对应的行列顺序

> p$tree_row$order
 [1]  4  6 15  8 12 14 10 11  2  1 16 17  3  7 13 18  5  9 19 20
> p$tree_col$order
[1] 4 5 6 2 1 3

提取这些信息有助于我们对数据进行分组,用于后续分析

参数列表


数据:
https://github.com/dxsbiocc/learn/blob/main/data/RPKM_DEG.csv

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

推荐阅读更多精彩内容