如何用R的circlize包创建不同扇区数量的环形轨道?
解决circlize包中不同轨道扇区数量不一致的问题
circlize的全局扇区由circos.initialize定义,后续轨道默认沿用这个扇区体系,直接用circos.track(sectors = 1:12)无法创建新的12个扇区,必须基于已初始化的36个细粒度扇区,通过合并多个小扇区实现中层12个、内层3个的视觉效果。
完整代码示例:
library(circlize) # 初始化36个扇区(最细粒度) sectors = 1:36 circos.par(gap.degree = 0, cell.padding = c(0, 0, 0, 0), start.degree = 360/20/2, track.margin = c(0, 0), clock.wise = FALSE) circos.initialize(sectors, xlim = c(0, 1)) # ---------------------- 外层轨道(36个扇区) ---------------------- circos.track(ylim = c(0, 1), sectors = sectors, bg.col = rep(c("lightblue", "lightgreen", 'lightyellow'), 12), bg.border = "black", track.height = 0.1) circos.trackText(x = rep(0.5, 36), y = rep(0.5, 36), labels = rep(c('A', 'B', 'C'), 12), cex = 0.8, sectors = sectors, col = "black", font = 2, facing = "downward") # ---------------------- 中层轨道(12个扇区,每3个外层扇区合并为1个) ---------------------- # 定义中层扇区与外层扇区的映射关系 mid_sector_map = rep(1:12, each = 3) # 创建空轨道(不自动绘制小扇区背景) circos.track(ylim = c(0, 1), track.height = 0.1, bg.border = NA) # 手动绘制每个中层扇区的背景(跨3个外层扇区) for (mid_id in 1:12) { # 获取当前中层扇区对应的所有外层扇区索引 outer_ids = which(mid_sector_map == mid_id) # 获取该组扇区的起始和结束角度 start_deg = get.cell.meta.data("cell.start.degree", sector.index = outer_ids[1]) end_deg = get.cell.meta.data("cell.end.degree", sector.index = outer_ids[length(outer_ids)]) # 绘制跨扇区的矩形背景 circos.rect(xleft = 0, ybottom = 0, xright = 1, ytop = 1, sector.index = outer_ids[1], track.index = get.current.track.index(), col = ifelse(mid_id %% 2 == 1, "lightcoral", "lightsalmon"), border = "black") } # 添加中层扇区文本(对应每个合并扇区的中心位置) circos.trackText(x = 0.5, y = 0.5, labels = 1:12, sector.index = seq(1, 36, by = 3), # 取每个合并组的第一个外层扇区作为文本位置 cex = 0.8, col = "black", font = 2, facing = "downward") # ---------------------- 内层轨道(3个扇区,每12个外层扇区合并为1个) ---------------------- # 定义内层扇区与外层扇区的映射关系 inner_sector_map = rep(1:3, each = 12) # 创建空轨道 circos.track(ylim = c(0, 1), track.height = 0.1, bg.border = NA) # 手动绘制每个内层扇区的背景(跨12个外层扇区) for (inner_id in 1:3) { outer_ids = which(inner_sector_map == inner_id) start_deg = get.cell.meta.data("cell.start.degree", sector.index = outer_ids[1]) end_deg = get.cell.meta.data("cell.end.degree", sector.index = outer_ids[length(outer_ids)]) circos.rect(xleft = 0, ybottom = 0, xright = 1, ytop = 1, sector.index = outer_ids[1], track.index = get.current.track.index(), col = c("mediumpurple", "goldenrod", "slategray")[inner_id], border = "black") } # 添加内层扇区文本 circos.trackText(x = 0.5, y = 0.5, labels = c("Group 1", "Group 2", "Group 3"), sector.index = c(1, 13, 25), # 每个合并组的第一个外层扇区位置 cex = 1, col = "white", font = 2, facing = "downward") # 清理circlize环境 circos.clear()
关键说明
circos.initialize定义的扇区是全局基础,所有轨道都基于这个粒度,无法直接在后续轨道中创建全新的扇区数量。- 通过手动绘制
circos.rect并指定跨多个基础扇区,可以实现合并扇区的视觉效果,每个合并扇区的角度范围由对应基础扇区的起始/结束角度决定。 - 文本位置选择每个合并组的第一个基础扇区即可,
x=0.5会自动对应该扇区的中心,与合并后的扇区中心重合。
内容的提问来源于stack exchange,提问作者Matt Jago
相关产品推荐
相关产品推荐

