1引言
在绘制分类数据较多的时候,不可避免的会出现大量重叠的样本名称,一个常见的情况就是绘制基因表达热图的时候基因多了,标记基因名就会重叠看不清,此外如果标记一部分基因名, 如果它们靠的太近,也会出现重叠看不清的情况, 一个好的解决方法是充分利用剩余的空间来将这些标签放置分配好。比较好的例子就是 ComplexHeatmap 包里的 anno_mark 函数可以指定标出部分基因。下面即示例:
那么如何去自己手动写一个自动绘制标签位置的小工具,方便可以应用在不同的场景呢?我们可以写一个 grob, 关于如何计算调整后的标签的位置, 一个简单的思路就是把空白的绘图区域等份的给每个标签的位置,然后用线将原来的位置的新的位置连接起来即可。
当然你也可以使用 ComplexHeatmap 包里的方法, 该包提供了 smartAlign2 函数,来通过原始位置计算调整后的位置,下面看看示例:
library(ComplexHeatmap)
range = c(0, 10)
pos1 = rbind(c(-0.5, 2), c(5, 7))
smartAlign2(pos1, range = range, plot = TRUE)
好了,我们可以先按自己的思路编写代码,然后加入 smartAlign2 选项就比较完美了,然后再增强一下可视化。
2参数
经过不断地 debug,测试,终于完成的差不多了,下面是一些参数:smartLabelAlignGrob <- function(all.label = NULL,
mark.label = NULL,
x = 0.5,y = 0.5,
use.smartAlign2 = FALSE,
link.line.length = 0.025,
link.label.space = 0.02,
mark.scale = c(0.01,0.99),
link.label.gp = gpar(fontsize = 10),
link.line.gp = gpar(fill = "black",col = "black"),
link.circle.start.gp = gpar(fill = "black",col = "black"),
link.circle.end.gp = gpar(fill = "black",col = "black"),
link.start.type = c("line","circle","arrow"),
link.end.type = c("line","circle","arrow"),
circle.arrow.size = c(0.01,0.01),
pos = c("right","left","top","bottom"),
name = NULL,
gp = NULL, vp = NULL){
lst <- list(all.label = all.label,
mark.label = mark.label,
x = x,y = y,
use.smartAlign2 = use.smartAlign2,
link.line.length = link.line.length,
link.label.space = link.label.space,
mark.scale = mark.scale,
link.label.gp = link.label.gp,
link.line.gp = link.line.gp,
link.circle.start.gp = link.circle.start.gp,
link.circle.end.gp = link.circle.end.gp,
link.start.type = link.start.type,
link.end.type = link.end.type,
circle.arrow.size = circle.arrow.size,
pos = pos,
name = name, gp = gp, vp = vp,
cl = "smartLabelAlignGrob")
do.call(gTree,lst)
}
3测试
位置标签均匀分布
假如我们画 50 个标签,想要标出其中一些, 你需要提供 所有的标签名称 和 需要标记的标签名称:library(grid)
library(tidyverse)
data(USArrests)
all.label <- rownames(USArrests)
mark.label <- sample(all.label,15,replace = F)
pagelabel <- function(hjust = 1,x = 0.48){
grid.newpage()
pushViewport(viewport(width = 0.5,height = 0.9,yscale = c(0.5,50.5)))
grid.text(x = x,y = unit(1:50,"native"),
label = all.label,
hjust = hjust)
}
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label))
设置起始和终止连接的形状:pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
link.start.type = "circle",
link.end.type = "arrow"))
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
link.start.type = "arrow",
link.end.type = "arrow"))
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
link.start.type = "circle",
link.end.type = "circle"))
设置一些颜色,大小:
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.03),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.circle.start.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic")))
smartAlign2 调用
设置 use.smartAlign2 = T 即可转换为 smartAlign2 计算的位置:pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
use.smartAlign2 = T))
其它设置也可以:pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.03),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic"),
use.smartAlign2 = T))
调整方向
当然你也可以调整方向:pagelabel(hjust = 0,x = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "left"))
pagelabel(hjust = 0,x = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "left",
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.03),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic")))
上下方向:pagelabel <- function(hjust = 1,y = 0.48){
grid.newpage()
pushViewport(viewport(width = 0.9,height = 0.9,xscale = c(0.5,50.5)))
grid.text(x = unit(1:50,"native"),y = y,
label = all.label,
hjust = hjust,
rot = 90)
}
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "top"))
pagelabel()
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "top",
link.start.type = "circle",
link.end.type = "circle"))
pagelabel(hjust = 0,y = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "bottom"))
pagelabel(hjust = 0,y = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "bottom",
link.start.type = "circle",
link.end.type = "circle"))
pagelabel(hjust = 0,y = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "bottom",
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.03),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic")))
调用 smartAlign2 :pagelabel(hjust = 0,y = 0.52)
grid.draw(smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "bottom",
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.025),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic"),
use.smartAlign2 = T))
4应用
既然是 grob 就可以应用在 ggplot 上面, 我们可以使用 annotation_custom 来插入到图里。下面举个例子, 顺便使用 ggh4x 来给热图添加聚类树, 然后你需要获取聚类后所有标签的顺序才好正确的注释:
# ==============================================================================
library(ggplot2)
library(ggh4x)
# get long data
scale.data <- t(scale(t(USArrests)))
df.long <- reshape2::melt(scale.data)
clusters.y <- hclust(dist(USArrests), "ave")
# ==============================================================================
# create anno grobs
all.label <- rownames(USArrests)[clusters.y$order]
mark.label <- sample(all.label,15,replace = F)
anno.grob <- smartLabelAlignGrob(all.label = all.label,
mark.label = mark.label,
pos = "right",
link.start.type = "circle",
link.end.type = "circle",
circle.arrow.size = c(0.01,0.025),
link.circle.end.gp = gpar(fill = rainbow(15)),
link.label.gp = gpar(fontface = "bold.italic"))
然后画图,设置一下 clip = “off” 关闭剪裁选项:ggplot(df.long) +
geom_tile(aes(x = Var2,y = Var1,fill = value)) +
theme_bw() + xlab("") + ylab("") +
scale_fill_gradient2(low = "blue",mid = "white",high = "red",midpoint = 0) +
scale_y_dendrogram(hclust = clusters.y) +
theme(legend.position = "top",
plot.margin = margin(r = 5,unit = "cm")) +
coord_cartesian(clip = "off") +
annotation_custom(grob = anno.grob,
xmin = 1,
xmax = 8.5)
可以看到注释的位置是正确的,使用 smartAlign2 看看,就不展示代码了:
5结尾
路漫漫其修远兮,吾将上下而求索。
欢迎加入生信交流群。加我微信我也拉你进 微信群聊 老俊俊生信交流群 (微信交流群需收取 20 元入群费用,一旦交费,拒不退还!(防止骗子和便于管理)) 。QQ 群可免费加入, 记得进群按格式修改备注哦。
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/372396.html