You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 05:07:45