如何在R语言circlize包的circos.heatmap中对组内元素按字母排序?
在circlize环形热图中实现分组内元素按字母单独排序
要实现每个分组内的元素(行名/列名)按字母单独排序,核心是先对每个分组内的元素排序,再重构数据和分组顺序,让circlize按照排序后的顺序渲染。以下是具体操作步骤:
核心思路
circlize的split参数是基于数据的原有顺序进行分组展示的,所以需要先手动拆分每个分组,对组内元素按字母排序,再重新组合成排序后的数据集,最后传入circos.heatmap()。
具体操作代码
1. 预处理数据(以行分组为例)
假设你有数据矩阵mat,以及和行对应的分组向量group:
# 拆分每个分组的行名,单独按字母排序 row_groups <- split(rownames(mat), group) sorted_rows <- unlist(lapply(row_groups, sort)) # 按排序后的行名重新整理矩阵和分组向量 mat_sorted <- mat[sorted_rows, ] group_sorted <- group[match(sorted_rows, rownames(mat))]
2. 绘制排序后的环形热图
用排序后的矩阵和分组向量调用circos.heatmap():
library(circlize) circos.clear() # 清空之前的绘图配置 # 设置分组间隙等参数,提升可读性 circos.par(gap.degree = 10) circos.heatmap(mat_sorted, split = group_sorted, # 使用排序后的分组向量 col = colorRamp2(c(-2, 0, 2), c("blue", "white", "red")), # 自定义颜色映射 border = "white") # 加白色边框区分元素 # 可选:添加分组标签 circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) { sector_name <- get.cell.meta.data("sector.index") circos.text(CELL_META$xcenter, CELL_META$ylim[1] - mm_y(5), sector_name, facing = "clockwise", niceFacing = TRUE) }, bg.border = NA) circos.clear() # 清理绘图环境
列分组的情况
如果是对列进行分组并排序,逻辑完全一致:只需将上述代码中的rownames换成colnames,调整矩阵的列顺序,分组向量对应列即可。
完整示例(含模拟数据)
# 生成模拟数据 set.seed(123) mat <- matrix(rnorm(100), nrow = 20) rownames(mat) <- paste0("Gene", sample(1:20)) # 打乱行名顺序 group <- rep(c("GroupA", "GroupB", "GroupC"), c(7, 6, 7)) # 分组内按行名字母排序 row_groups <- split(rownames(mat), group) sorted_rows <- unlist(lapply(row_groups, sort)) mat_sorted <- mat[sorted_rows, ] group_sorted <- group[match(sorted_rows, rownames(mat))] # 绘制环形热图 library(circlize) circos.clear() circos.par(gap.degree = 10) circos.heatmap(mat_sorted, split = group_sorted, col = colorRamp2(c(-2, 0, 2), c("#2c7fb8", "#ffffff", "#d95f02")), border = "white") # 添加分组标签 circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) { sector_name <- get.cell.meta.data("sector.index") circos.text(CELL_META$xcenter, CELL_META$ylim[1] - mm_y(5), sector_name, facing = "clockwise", niceFacing = TRUE) }, bg.border = NA) circos.clear()
内容的提问来源于stack exchange,提问作者mereda
相关产品推荐
相关产品推荐

