修复Circlize弦图轴编号错位及Calibri粗体字体设置问题
R circlize包弦图自定义轴的两类问题解决方案
问题说明
使用circlize包绘制弦图、按固定间隔设置自定义主刻度时,出现两类异常:
- 轴标签位置错位:调整字体大小后,各扇区外侧轴标签向内偏移,偏移程度随字体增大而提升,出现0刻度脱离对应刻度标记、C/D/J等扇区轴标签内移重叠的问题
- 字体配置不生效:通过
extrafonts、showtext包加载Calibri字体后,无法在绘图中正常调用该字体,也无法实现粗体效果
原始复现代码
示例邻接矩阵
#sample matrix A<-c(4680,0,0,0,0,0,0,0,0,0) B<-c(109,23323,0,0,0,0,0,0,0,0) C<-c(9,12,5405,0,0,0,0,0,0,0) D<-c(19,25,26,4615,0,0,0,0,0,0) E<-c(108,816,32,38,5511,0,0,0,0,0) F_1<-c(50,319,67,55,202,18198,0,0,0,0) G<-c(15,11,8,178,11,18,38279,0,0,0) H<-c(24,180,22,39,171,212,14,10673,0,0) I<-c(211,2378,18,28,1603,251,25,188,34458,0) J<-c(162,1623,31,48,1003,370,34,265,5319,27235) m <- rbind(A,B,C,D,E,F_1,G,H,I,J) row.names(m) <- LETTERS[seq(1,10,1)] colnames(m)<- LETTERS[seq(1,10,1)]
原始绘图代码
colfunc <- colorRampPalette(c("#856705", "#d3d3d3", "#113069")) grid.col <- setNames(colfunc(10), LETTERS[seq(1,10,1)]) grid.col library(showtext); library(circlize) #my attempt to load the correct font but I am unsure how to call the font within circlize. font_add(family = "Calibri", regular = "C:/Windows/Fonts/calibri.ttf", italic ="C:/Windows/Fonts/calibrii.ttf", bold = "C:/Windows/Fonts/calibrib.ttf", bolditalic = "C:/Windows/Fonts/calibriz.ttf") circos.clear() showtext_auto() circos.par(start.degree = 90, gap.degree = 5) par(family = "Calibri") #tried to set the family to "Calibri" chordDiagram(m/1000, transparency = 0.5, grid.col = grid.col, annotationTrack = "grid", self.link = 1, link.lwd = 0.5, # Line width link.lty = 1, link.border = "light grey", annotationTrackHeight = mm_h(10)) for(si in get.all.sector.index()) { circos.axis(h = 'top', major.at = c(0,5,10,15,20,25,30,35,40,45,50), labels = c(0,5,10,15,20,25,30,35,40,45,50), minor.ticks = 4, labels.cex = fontsize(30), sector.index = si, track.index = 1, labels.niceFacing = TRUE) xlim = get.cell.meta.data("xlim", sector.index = si, track.index = 1) ylim = get.cell.meta.data("ylim", sector.index = si, track.index = 1) circos.text(mean(xlim), mean(ylim), si, sector.index = si, track.index = 1, niceFacing = TRUE, cex = fontsize(50), col = "white", font = par("Calibri")) } dev.copy(png, "test chord diagram.png", width = 5, height = 5, units = "cm", res = 600) dev.off() circos.clear()
问题原因与修复方法
轴标签偏移问题
三个原因共同导致该异常:
- 给所有扇区硬编码了统一的0-50刻度序列,但不同扇区的轴长度差异极大(比如C扇区总长度仅5.4左右),超出扇区范围的刻度值会强制渲染,导致刻度与标签位置错位
circos.axis默认标签偏移量适配小字体,大字体下没有预留足够外移距离,标签会向内挤压重叠- 使用
dev.copy()导出图片时,会因屏幕设备与输出设备的分辨率映射差,导致元素位置偏移
修复操作:
- 遍历每个扇区时,基于扇区自身的x轴范围生成对应间隔的刻度点,不要硬编码全局统一刻度
- 在
circos.axis()中添加labels.offset参数,根据字体大小设置合适的向外偏移值 - 导出图片时先调用
png()初始化输出设备,绘图完成后再调用dev.off(),不要用dev.copy()转存
字体失效问题
两个参数写法错误导致字体与粗体不生效:
circos.text()中的font参数是字重控制参数(取值1=常规、2=粗体、3=斜体、4=粗斜体),不能传入字体名称,原代码中font = par("Calibri")属于无效传参circlize内部绘图会重置部分全局绘图参数,仅在开头用par(family=)设置全局字体无法传递到所有circlize渲染的元素中
修复操作:
- 所有文本类元素(轴标签、扇区标识文字)显式传入
family = "Calibri"指定字体 - 需要粗体效果时,对应元素设置
font = 2即可
修复后完整代码
colfunc <- colorRampPalette(c("#856705", "#d3d3d3", "#113069")) grid.col <- setNames(colfunc(10), LETTERS[seq(1,10,1)]) library(showtext) library(circlize) # 加载Calibri字体,确认路径与本地文件匹配 font_add(family = "Calibri", regular = "C:/Windows/Fonts/calibri.ttf", italic ="C:/Windows/Fonts/calibrii.ttf", bold = "C:/Windows/Fonts/calibrib.ttf", bolditalic = "C:/Windows/Fonts/calibriz.ttf") circos.clear() showtext_auto() # 先初始化png输出设备,避免dev.copy导致的位置错位 png("test chord diagram.png", width = 5, height = 5, units = "cm", res = 600) circos.par(start.degree = 90, gap.degree = 5) chordDiagram(m/1000, transparency = 0.5, grid.col = grid.col, annotationTrack = "grid", self.link = 1, link.lwd = 0.5, link.lty = 1, link.border = "light grey", annotationTrackHeight = mm_h(10)) for(si in get.all.sector.index()) { xlim = get.cell.meta.data("xlim", sector.index = si, track.index = 1) ylim = get.cell.meta.data("ylim", sector.index = si, track.index = 1) # 基于当前扇区的x轴范围生成5间隔的刻度,避免超出范围的无效刻度 max_val <- ceiling(xlim[2]/5)*5 major_ticks <- seq(0, max_val, 5) circos.axis(h = 'top', major.at = major_ticks, labels = major_ticks, minor.ticks = 4, labels.cex = fontsize(30), sector.index = si, track.index = 1, labels.niceFacing = TRUE, labels.offset = 0.3, # 大字体下增加标签向外偏移量,可根据实际效果调整数值 labels.family = "Calibri") # 轴标签指定Calibri字体 circos.text(mean(xlim), mean(ylim), si, sector.index = si, track.index = 1, niceFacing = TRUE, cex = fontsize(50), col = "white", family = "Calibri", # 指定字体 font = 2) # 2对应粗体效果 } dev.off() circos.clear()
内容的提问来源于stack exchange,提问作者Dustin
相关产品推荐
相关产品推荐

