当前位置: 首页 > ds >正文

Circular Plot系列(一): 环形热图绘制

针对近期多个粉丝咨询环形图的绘制,我意识到,我们似乎没有真正介绍过circle图,但这一类图确是非常常用的图,所以这里详细学习一下circle的绘制,使用的是circlize包,功能很完善:安装包,


#https://github.com/jokergoo/circlize/tree/master
#install package
install.packages("circlize")
#devtools::install_github("jokergoo/circlize")
library(circlize)

做环形热图使用circos.heatmap函数,我们看看具体的参数解析:

#了解下环形热图绘制circos.heatmap基本参数。
circos.heatmap(mat, #矩阵或者向量,矩阵就是和我们做hetamap的时候提供的一样,例如行是基因,列是分组sample,向量的化会自动转化为一个单列矩阵,说到底还是矩阵,适合于plot单组数值split = NULL, #环线热图分列,例如我们可以设置分组,让热图分为多个扇形col, #热图颜色设置,参照colorRamp2,设置颜色和范围,例如一般设置:colorRamp2(c(-2, 0, 2), c("blue", "white", "red"))cell.border = NA, #r热图格子边框颜色,默认NA不设置cell.lwd = 1,#边框线条宽度bg.border = NA, #cell.border设置的是每个单元格的边框,bg.border设置的是整个热图外边框颜色bg.lty = par("lty"),#整个热图边框线条类型,可以直接设置数字,例如1,2,3等等,选择是实线还是虚线类型的线条bg.lwd = par("lwd"),#整个热图边框线条宽度,可直接设置数值cluster = TRUE, #热图行是否聚类。该值也可以是一个dendprogram /hclust对象或其他可以用as. dendprogram转换为的对象。也就是所已经做好聚类的objectclustering.method = "complete", #聚类方法,参照hclust函数,可选"ward.D", "ward.D2", "single", "complete", "average" (= UPGMA), "mcquitty" (= WPGMA), "median" (= WPGMC) or "centroid" (= UPGMC).distance.method = "euclidean",#参照dist函数,method可选"euclidean", "maximum", "manhattan", "canberra", "binary" or "minkowski". # dend.callback = function(dend, m, si) reorder(dend, rowMeans(m)),dend.side = c("none", "outside", "inside"), #聚类树位置,默认不展示。可选择外圈或者内圈放置dend.track.height = 0.1,#聚类树高度rownames.side = c("none", "outside", "inside"), #行名位置,默认不展示。可选择外圈或者内圈放置rownames.cex = 0.5,#行名文字大小rownames.font = par("font"), #行名字体rownames.col = "black",#行名颜色cell_width = rep(1, nrow(mat)),#热图单元格宽度

准备作图数据,这里我们使用转录组基因表达矩阵演示:


#prepare data
#这是一个转录组基因表达矩阵,也是我们常做pheatmap的输入矩阵
#行是基因,列是分组,有两个分组,HC,TL,分别有6个重复
df <- read.csv('./df_heat.csv', header = T, row.names = 1)
plot_df <- as.matrix(df)
#因为circos.heatmap没有像pheatmap那样,直接参数里面对数据进行scale
#所以我们plot之前需要对表达数据进行标准化,如果仅仅是想展示数值,那么数据并不用标准化
plot_df <- t(scale(t(plot_df)))#对数据进行标准化处理,按行z-score标准化

基础plot:布局也是绘图关键哦,了解下布局一些参数,可以调整:不可死板。

circos.par(start.degree,#数值,设置环形图的起始角度。0是其实,位于3点钟方向,数值增大,开口逆时针移动gap.degree,#数值或数值向量,设置扇区之间的间隔角度.单个数值设置表示多个扇区之间距离一致。向量可设置不一样间隔gap.after, #设置圆环开口的大小,数值越大,开口越大track.margin,#数值向量,设置轨道的上下边距cell.padding,#设置单元格的内边距,扇形内格子之间的距离,一般设置为0track.height,#设置轨道的高度,也就是圆环的宽度,默认0.2clock.wise,#设置环形方向是否为顺时针,默认Tlabels.cex,#设置文字大小labels.font,#设置文字字体,1=普通,2=粗体,3=斜体,4=粗斜体)unit.circle.segments,#设置绘制圆时的线段数量(影响圆形的平滑度),默认500big.gap,#设置两个环形图之间的间隔角度(用于多环形图)circle.margin,#环形图布局,图形距离四边的距离,数值向量设置。..., RESET = FALSE, READ.ONLY = NULL, LOCAL = FALSE, ADD = FALSE)

#布局设置
circos.clear()
circos.par(start.degree=30, gap.degree=30,track.height=0.3)circos.heatmap(plot_df,col = colorRamp2(c(-2,0,2),c("#003399","white","#cccc00")), cell.border = NA, cell.lwd = 1,bg.border = 'black', bg.lty = par("lty"),bg.lwd = par("lwd"),cluster = TRUE, clustering.method = "ward.D2", distance.method = "euclidean",dend.side = c("inside"), dend.track.height = 0.1,rownames.side = c("outside"),rownames.cex = 0.5,#行名文字大小rownames.font = par("font"), #行名字体rownames.col = "black")

image.png

基础图形出来了,感觉把平常的热图给掰弯了,现在还缺少legend和sample名:添加是比较麻烦的,需要为整个轨道创建绘图区域,使用函数circos.track():添加文字使用circos.text,列名的位置需要根据自己的实际数据,调整x,y轴的坐标慢慢实现,如果感觉调整费时间,可以导出手动修饰,这也是circlize的一个不方便之处。


circos.track(track.index = get.current.track.index(),  # 指定当前轨道的索引panel.fun = function(x, y) {            #panel.fun,自定义绘制函数,用于在轨道中添加图形或注释if (CELL_META$sector.numeric.index == 1) {  # 仅在第一个扇区执行cn = colnames(plot_df)  # 获取数据框的列名n = length(cn)          # 列名的数量#添加文字注释,参数需要设置文字位置xy坐标circos.text(x = CELL_META$cell.xlim[2] + convert_x(0.8, "mm"),#x坐标y = CELL_META$cell.ylim[2] + 4.5 * (1:n),  # y 坐标,labels = rev(cn),       # 文本内容(列名),这里需要注意,rev一下,保证标注正确cex = 0.4,         # 字体大小facing = "inside"  # 文本方向(朝内))}},bg.border = NA  # 轨道背景无边框
)

image.png

然而,我们前面也介绍了,circos.heatmap有一个参数,split,热图可以按照行的分组split,这里演示split以及添加分组注释。其他和之前一致。我的数据并没有分组,这里随机设置的,没有任何意义。将基因按照功能进行了分组。

annotation_row=data.frame(Pathway=c(rep("Wnt",20),rep("Inflammatory",32),rep("HIF",34)))#对行进行注释,用于后续的热图分裂
row.names(annotation_row) <- rownames(df)
annotation_row <- as.matrix(annotation_row)#在circlize函数中,需要为matrix#plot,画图和之前一样,需要注意的是布局设置的gap.degree
#这里我们有三组,也就是split时出现三组扇区,前面两个扇区的gap设置小点
#最后一个设置大一点,便于添加列名
circos.clear()
circos.par(start.degree=30, gap.degree=c(2,2,30),track.height=0.3)
circos.heatmap(plot_df,split = annotation_row,col = colorRamp2(c(-2,0,2),c("#003399","white","#cccc00")), cell.border = NA, cell.lwd = 1,bg.border = 'black', bg.lty = par("lty"),bg.lwd = par("lwd"),cluster = TRUE, clustering.method = "ward.D2", distance.method = "euclidean",dend.side = c("inside"), dend.track.height = 0.05,rownames.side = c("outside"),rownames.cex = 0.5,#行名文字大小rownames.font = par("font"), #行名字体rownames.col = "black",dend.callback=function(dend,m,si){color_branches(dend,k=5,col=c("#E69253", "#EDB931", "#E4502E", "#4378A0", "#272A2A"))})#还可以对层次聚类添加颜色,按照聚类数#
circos.track(track.index = get.current.track.index(),  # 指定当前轨道的索引panel.fun = function(x, y) {            #panel.fun,自定义绘制函数,用于在轨道中添加图形或注释if (CELL_META$sector.numeric.index == 3) {  # 仅在第一个扇区执行cn = colnames(plot_df)  # 获取数据框的列名n = length(cn)          # 列名的数量#添加文字注释,参数需要设置文字位置xy坐标circos.text(#这里我们将列名绘制在环形的尾部,我们前面参数里面解释了,环形是默认顺时针绘制的x = CELL_META$cell.xlim[2] + convert_x(0.8, "mm"),#前面的部分是获取行的长度,也就是绘制文字的x坐标,后面convert_x是调整参数,0.5表示文本向右偏移0.5y = CELL_META$cell.ylim[2] + 12 * (1:n),  # y 坐标,labels = rev(cn),       # 文本内容(列名),这里需要注意,rev一下,保证标注正确cex = 0.4,         # 字体大小facing = "inside"  # 文本方向(朝内))}},bg.border = NA  # 轨道背景无边框
)#添加分组设置,我们直接接上一个图层plot,这里没有设置track.index,所以注释在内圈
circos.track(ylim=c(0,1),track.height=0.081,#分组注释环形高度,可以设置低一点bg.col=c("#FF0000", "#00A08A", "#F2AD00"),#分组注释背景颜色panel.fun=function(x, y) {xlim = get.cell.meta.data("xlim")ylim = get.cell.meta.data("ylim")sector.index = CELL_META$sector.indexcircos.text(mean(xlim),mean(ylim),sector.index, col = "black", cex = 0.8, facing = 'bending.inside', niceFacing = TRUE)})

image.png

http://www.xdnf.cn/news/4063.html

相关文章:

  • 《马小帅的Java闯关记》
  • 模型部署与提供服务
  • QpushButton 扩展InteractiveButtonBase
  • k230摄像头初始化配置函数解析
  • nproc命令查看可用核心数量详解
  • [Windows] 智绘教 v20250403a 屏幕批注工具
  • day 12 三种启发式算法:遗传算法、粒子群算法、退火算法
  • 用卷积神经网络 (CNN) 实现 MNIST 手写数字识别
  • Python函数完全指南:从零基础到灵活运用
  • 深度学习中保存最优模型的实践与探索:以食物图像分类为例
  • GTID(全局事务标识符)的深入解析
  • 高翔《视觉SLAM十四讲》中第13讲,单目稠密重建中的RMODE数据集
  • TS 元组
  • 2025年PMP 学习三
  • 游戏开发的TypeScript(4)TypeScript 的一些内置函数
  • TF-IDF算法详解
  • C# 定时器实现
  • 正态分布习题集 · 题目篇
  • 递归算法详解(Java 实现):从原理到高阶应用
  • 类和对象(上)
  • C语言 指针(5)
  • 两台电动缸同步算法
  • n8n 构建一个 ReAct AI Agent 示例
  • 数理性能大幅提升|暴雨一体机适配DeepSeek Prover v2
  • C++类_成员函数指针
  • 移动 Trae 目录到 E 盘 - 解决 C 盘空间不足问题
  • 在Qt Creator中使用CUDA
  • 录播课制作技术指南
  • Javase 基础加强 —— 03 集合
  • Room + WorkManager的Android学习总结