前面我们在人工智能大模型不会告诉你的热图绘制技巧 演示了如何使用ggplot2热图扩展包(ggalign),可以快速替代之前的 pheatmap:
比如我们可以先去geo数据库里面下载 GSE104171_NormalizedMatrix.txt.gz 这个文件,然后提取里面的指定的基因的表达量矩阵:
rm(list = ls())#清空当前的工作环境
options(stringsAsFactors = F)#不以因子变量读取
options(scipen = 20)#不以科学计数法显示
library(data.table)
library(tinyarray)
data<-data.table::fread("GSE104171_NormalizedMatrix.txt.gz",
data.table = F)
data=data[!duplicated(data$V1),]
mat<-data[,c( 2:ncol(data))]
rownames(mat)=data[,1]
mat[1:4,1:4]
keep_feature <- rowSums (mat > 1) > 1 ;table(keep_feature)
ensembl_matrix <- mat[keep_feature, ]
rownames(ensembl_matrix)=rownames(mat)[keep_feature]
ensembl_matrix[1:4,1:4]
symbol_matrix=ensembl_matrix
symbol_matrix[1:4,1:4]
colnames(symbol_matrix)
library(AnnoProbe)
head(rownames(symbol_matrix))
ids=annoGene(rownames(symbol_matrix),'SYMBOL','human')
head(ids)
tail(sort(table(ids$biotypes)))
ids=ids[ids$biotypes=='protein_coding',]
symbol_matrix=symbol_matrix[rownames(symbol_matrix) %in% ids$SYMBOL,]
colnames(symbol_matrix)
boxplot(symbol_matrix[,1:4])
cor_gene<-c('CD2','CD3E','CD3D','TBX21','CD8B','PRF1',
'GZMA','GZMB','ITGAM','ARG1','CYBB','OLR1',
'FUT4','CEACAM8','S100A8','S100A9')
exprSet=symbol_matrix[cor_gene,]
可以看到,是16个基因在74个样品的表达量矩阵:
我们首先呢,使用pheatmap绘图 :
p1=pheatmap::pheatmap(cor(t(exprSet)))
matrix_chosen<-t(scale(t(exprSet)))
tmp<-colnames(matrix_chosen)
tmp<-rep('',ncol(matrix_chosen))
p2=pheatmap::pheatmap(matrix_chosen,labels_col=tmp,
legend_breaks=seq(-3,3,1))
hc=cutree(p2$tree_col,2)
# MN-MDSC signature genes (ITGAM, ARG1, CYBB, OLR1, FUT4, CEACAM8, S100A8, and S100A9)
# cytotoxic lymphocyte signature genes (CD2, CD3E, CD3D, TBX21, CD8B, PRF1, GZMA, and GZMB)
ac=as.data.frame(as.character(hc))
rownames(ac)=colnames(matrix_chosen)
p3=pheatmap::pheatmap(matrix_chosen,labels_col=tmp,
annotation_col = ac,
legend_breaks=seq(-3,3,1))
library(cowplot)
require(ggplotify)
cowplot::plot_grid(as.ggplot(p1) , as.ggplot(p3), ncol=2)
可以看到,比较麻烦的把样品分成了两组:
如果是ggalign就一句话 :
library(ggalign)
ggheatmap(matrix_chosen) +
scale_fill_viridis_c() +
hmanno("t") +
align_dendro(aes(color = branch), k = 2) +
geom_point(aes(color = branch, y = y)) +
scale_color_brewer(palette = "Dark2")
同样的可以把样品分成两组:
ggalign
通过对齐多个ggplot2
图表的观测来组织图表布局。它使你能够使用熟悉的 ggplot2 语法创建复杂热图。
你可以使用以下命令从 CRAN
安装 ggalign
:
install.packages("ggalign")
或者,从 GitHub 安装开发版本(目前开发版本添加了大量新功能,因为CRAN通常需要1-2个月的更新间隔,暂不能推送到CRAN):
# install.packages("remotes")
remotes::install_github("Yunuuuu/ggalign")
如果你熟悉 ggplot2
语法,ggalign
的使用很简单,典型的工作流程如下:
ggheatmap()
或 ggstack()
初始化布局。align_group()
:将布局轴分组到具有组变量的面板中。align_kmeans()
:通过 kmeans 将布局轴分组到面板中。align_order()
:根据统计权重重新排序布局观察结果,或手动指定观察索引。align_dendro()
:根据层次聚类重新排序或分组布局。ggalign()
或 ggpanel()
添加图表,然后叠加额外的 ggplot2 元素,如 geoms、stats 或 scales。下面,我们将通过一个基本示例,展示如何使用 ggalign
创建带有 dendrogram
的热图。
library(ggalign)
set.seed(123)
small_mat <- matrix(rnorm(81), nrow = 9)
rownames(small_mat) <- paste0("row", seq_len(nrow(small_mat)))
colnames(small_mat) <- paste0("column", seq_len(ncol(small_mat)))
# 初始化热图布局,我们可以将其视为一个普通的 ggplot 对象
ggheatmap(small_mat) +
# 我们可以直接修改 geoms、scales 和其他 ggplot2 组件
scale_fill_viridis_c() +
# 在顶部添加注释
hmanno("top") +
# 在顶部注释中,我们添加了一个树状图,并将观察结果分成 3 组
align_dendro(aes(color = branch), k = 3) +
# 在树状图中添加点 geom
geom_point(aes(color = branch, y = y)) +
# 更改树状图的颜色映射
scale_color_brewer(palette = "Dark2")
ggalign
相对于其他扩展如 ggheatmap 的主要优势在于其与 ggplot2 语法的完全兼容性。你可以无缝使用任何 ggplot2 geoms、stats 和 scales 来构建复杂布局,包括垂直或水平排列的多个热图。
ggplot2
生态系统完全集成。ggplot2
图表对齐。内置注释较少:与 ComplexHeatmap 中广泛的内置注释函数相比,可能需要额外编写更多代码以实现特定图形。
以下是使用 ggalign
进行的一些更高级的可视化示例:
heatmap_layout()
/ggheatmap
函数用来初始化热图布局
数据输入可以是数值或字符向量、数据框,以及任何可以转换为矩阵的数据。
set.seed(123)
small_mat <- matrix(rnorm(81), nrow = 9)
rownames(small_mat) <- paste0("row", seq_len(nrow(small_mat)))
colnames(small_mat) <- paste0("column", seq_len(ncol(small_mat)))
library(ggalign)
ggheatmap(small_mat)
对于 ggplot2,矩阵在绘制时会被转换为长格式的数据框。默认的映射将使用 aes(.data.x, .data.y),但可以通过 mapping 参数进行控制。ggplot2 对象的数据包含以下列:
.xpanel
和 .ypanel
: 列和行的panel groups.x
和 .y
: x 和 y 坐标.row_names
和 .column_names
: 原始矩阵的行和列名(仅在名称存在时出现).row_index
和 .column_index
: 原始矩阵的行和列索引。value
: 实际的矩阵值。我们可以像处理普通的 ggplot2 对象一样处理 ggheatmap()
对象,例如添加 ggplot2 geoms, stats, scales以及theme。
ggheatmap(small_mat) + geom_point() + scale_fill_viridis_c()
默认情况下,我们会添加热图层。如果设置 filling = FALSE
,则会绘制一个空白的热图。你可以自定义热图图层,对于大数据集,你可以将图层像素化从而提高渲染速度,这里我们使用ggrastr
来像素化图层。
ggheatmap(small_mat, filling = FALSE) +
ggrastr::rasterize(geom_tile(aes(fill = value)))
热图注释可为热图的行或列提供额外信息,可以放置在热图四周。ggheatmap()
使用活动上下文
来控制注释信息的位置。默认情况下,ggheatmap()
不会初始化活动上下文
,因此所有添加的内容(包括ggplot2元件)都将直接添加进热图主体。您可以使用 hmanno()
来设置活动上下文
。
除了ggplot2元件
外,我们还可以在注释中添加任何align_*()
函数,align_*()
函数可以添加图表,也可以自定义布局,例如排序,聚类,分组等。目前,有四个 align_*
函数可用于图表布局控制:
align_group
:根据分类因子对图表进行分组和对齐。align_order
:根据统计权重重新排序布局观察值,或允许根据用户定义的标准手动重新排序。align_kmeans
:根据 k-means 聚类结果排列图表。align_dendro
:根据层次聚类或树状图对图表进行对齐。align_group
align_group()
函数将行/列进行分组。它不会添加任何绘图区域。
ggheatmap(small_mat) +
hmanno("t") +
align_group(sample(letters[1:4], ncol(small_mat), replace = TRUE))
默认情况下,ggplot2面板标题会被移除。您可以使用 theme(strip.text = element_text())
来选择在那个绘图区域添加facet标题。由于 align_group()
不创建新图表,因此面板标题只能添加到热图中。
ggheatmap(small_mat) +
theme(strip.text = element_text()) +
hmanno("l") +
align_group(sample(letters[1:4], nrow(small_mat), replace = TRUE))
align_order
align_order()
函数可对行/列进行排序。像 align_group()
一样,它不会增加绘图区域。
在这里,我们根据均值重新排序行。
ggheatmap(small_mat) +
hmanno("l") +
align_order(rowMeans)
此外,我们可以直接提供排序的索引(数值/字符)。
my_order <- sample(nrow(small_mat))
print(rownames(small_mat)[my_order])
#> [1] "row3" "row1" "row7" "row6" "row2" "row8" "row9" "row5" "row4"
ggheatmap(small_mat) +
hmanno("l") +
align_order(my_order)
ggheatmap(small_mat) +
hmanno("l") +
align_order(rownames(small_mat)[my_order])
默认情况下,align_order()
会根据函数的输出结果(对于行,从底部到顶部;对于列,从左到右)按升序重新排序行或列。可以通过 reverse = TRUE
反转顺序:
ggheatmap(small_mat) +
hmanno("l") +
align_order(rowMeans, reverse = TRUE)
一些 align_*
函数接受 data
参数。如果 data
参数为 NULL
,函数将使用布局的默认数据,如前例所示。data
参数还可以接受一个函数(支持 lambda 语法),该函数将应用于布局数据。
需要注意的是,所有 align_*
函数都将行视为观测。这意味着 NROW(data)
必须与特定的 layout
轴返回相同的观测数。
heatmap_layout()
/ggheatmap()
:对于列注释,layout
数据将在使用转置t
(如果数据是 function
,它将应用于转置后的矩阵)。因为列注释使用热图列作为观察值,但我们需要行。
因此,即使是顶部和底部注释,我们也可以使用 rowMeans()
计算所有列的平均值。
ggheatmap(small_mat) +
hmanno("t") +
align_order(rowMeans)
align_kmeans
align_kmeans()
函数根据 k-means 聚类对热图行或列分组,它也不会增加绘图区域。
ggheatmap(small_mat) +
hmanno("t") +
align_kmeans(3L)
align_dendro
align_dendro()
函数可以根据层次聚类重新排序或分割布局,同时它也可添加树状图。
ggheatmap(small_mat) +
hmanno("t") +
align_dendro()
树状图也可以用来将列/行切割成组。您可以指定 k
或 h
,其工作原理等同于于 cutree()
:
ggheatmap(small_mat) +
hmanno("t") +
align_dendro(k = 3L)
与 align_group()
、align_kmeans()
和 align_order()
不同,align_dendro()
可添加绘制图区域,我们可对其添加其他图层。
ggheatmap(small_mat) +
hmanno("t") +
align_dendro() +
geom_point(aes(y = y))
align_dendro()
函数为 ggplot 创建了默认的 node
数据。有关详细信息,请参见 ?align_dendro
中的 ggplot2 specification
。此外,edge
数据直接添加到 ggplote::geom_segment()
图层中,用于绘制树状图。node
和 edge
数据中的有一个branch
列,对应于 cutree
结果:
ggheatmap(small_mat) +
hmanno("t") +
align_dendro(aes(color = branch), k = 3) +
geom_point(aes(color = branch, y = y))
通过设置reorder_dendrogram
参数align_dendro()
可以根据观测均值对聚类树进行重排,
h1 <- ggheatmap(small_mat) +
hmanno("t") +
align_dendro(aes(color = branch), k = 3, reorder_dendrogram = TRUE) +
ggtitle("reorder_dendrogram = TRUE")
h2 <- ggheatmap(small_mat) +
hmanno("t") +
align_dendro(aes(color = branch), k = 3) +
ggtitle("reorder_dendrogram = FALSE")
align_plots(h1, h2)
align_dendro()
函数还可以在组内进行聚类,这意味着即使在布局中存在现有的组,也可以使用它:
column_groups <- sample(letters[1:3], ncol(small_mat), replace = TRUE)
ggheatmap(small_mat) +
hmanno("t") +
align_group(column_groups) +
align_dendro(aes(color = branch))
您可以通过设置 reorder_group = TRUE
对组进行重新排序。
ggheatmap(small_mat) +
hmanno("t") +
align_group(column_groups) +
align_dendro(aes(color = branch), reorder_group = TRUE)
您可以通过设置 merge_dendrogram = TRUE
合并每个组中的子树。
ggheatmap(small_mat) +
hmanno("t") +
align_group(column_groups) +
align_dendro(aes(color = branch), merge_dendrogram = TRUE)
您可以同时排序以及合并树状图。
ggheatmap(small_mat) +
hmanno("t") +
align_group(column_groups) +
align_dendro(aes(color = branch),
reorder_group = TRUE,
merge_dendrogram = TRUE
) +
hmanno("b") +
align_dendro(aes(color = branch),
reorder_group = FALSE,
merge_dendrogram = TRUE
)
感兴趣更多细节的小伙伴务必去看看:https://yunuuuu.github.io/ggalign/