查看: 1677|回复: 4

[R语言] 标签糊成一坨?如何为图表添加“帅帅”的指引线?

[复制链接]

管理员

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

主题
153
注册时间
2019.7.8
在线时间
243 小时

发表于 2020.5.28 09:57:13 | 显示全部楼层 |阅读模式
在Seurat的输出结果中,有一个展示表达量变化最大10个基因的图表令人印象深刻,如下图。关于该图表的具体内容参考之前《单细胞转录组学习笔记之Seurat 3.0(一)》一文。那么,常规散点图能不能画成这样效果?


如果仍然使用针对单细胞数据高度定制的Seurat,显然是非常麻烦的。而使用ggplot2绘制类似这样的多标签图表,又容易出现“数据标签重叠”、超出绘图区域的标签“显示不全“和邻近数据点”指示不明“三大难题。
于是ggrepel这个R包应用而生,它让文字标签周围产生“力场”,相互排斥,相互靠近的点会添加“指引线”避免指示不明。

整个R包主要有两个用法几乎一样的函数geom_text_repel()和geom_label_repel(),可以把它们视作ggplot2中geom_text()的加强版,很显然,Seurat集成了这个R包。下面就仍以上图的数据为例,一起看下具体如何使用ggrepel吧!

数据准备

这里的范例数据表格是直接从《单细胞转录组学习笔记之Seurat 3.0(一)》一文中Seurat对象中导出的。为了方便大家练习,本文范例数据已上传到OmicShare论坛,登陆后下载即可。

下载链接:https://www.omicshare.com/forum/thread-6312-1-1.html
[AppleScript] 纯文本查看 复制代码
[/align]
[align=left]#读入数据:[/align]
[align=left]var.df <- read.table("var.genes.xls",header = T,sep = "\t")[/align]
[align=left]head(var.df,10)[/align]
[align=left]


[AppleScript] 纯文本查看 复制代码
#载入dplyr包;
library(dplyr)
#按照variance.standardized这一列数值降序排列;
var.genes<-arrange(var.df,desc(vst.variance.standardized))
head(var.genes,10)
为了检验这个包的性能,我这里选择绘制15个标签,当然选择展示20个也没问题。
#提取TopN基因集:
n <- 15
topn <- head(var.genes$gene,n)
topn
#追加标签列;
var.genes$labels <- ""
var.genes$labels[1:n] <- topn
head(var.genes,10)


关于“散点”叠放细节调整,将数据改为升序排列,目的是先画非高变基因,关注Topn的基因最后再画,实现后者的散点置于“顶层”效果。

[AppleScript] 纯文本查看 复制代码
var.genes<-arrange(var.genes,vst.variance.standardized)


添加箭头

[AppleScript] 纯文本查看 复制代码
#载入所需的画图主力R包;
library(ggplot2)
library(ggrepel)
#常规的geom_text()函数的效果;
p1 <- ggplot(data = var.genes,aes(log10(vst.mean),vst.variance.standardized,
color=vst.variable,label=labels)) +
geom_point()
p1+geom_text(color="grey20",size=3)


从上图我们可以看出,如果直接使用ggplot2的geom_text()函数会出现文本标签相互重叠的情况(虚线椭圆所示),也会出现标签对邻近的点指示不明的情况,如上图的CLU、NKG7基因。那么如何避免上述问题呢?我们先使用一下geom_text()函数的加强版:geom_text_repel()。

[AppleScript] 纯文本查看 复制代码
set.seed(100)
p2 <- p1+geom_text_repel(color="grey20",size=3,point.padding = NA)
p2


geom_text_repel()和geom_label_repel()的核心参数:
nudge_x/y:数据点与相应数据标签的距离,例如1表示标签在点右/上的1个单位处,而-2.2表示标签在点左/下2.2个单位处;
direction:标签分布方向,x表水平分布,y 表示垂直分布,both 表示随机分布;
segment.size:指定线段的粗细;
point.padding:表示点周围的空余区域,决定连接线端点到到数据点中心的距离,单位为line。


标签的“排斥”效果很不错,但是还不够“高大上”。接着,在垂直方向上给标签多一些偏移,并绘制箭头指引线。

[AppleScript] 纯文本查看 复制代码
p3 <- p1+geom_text_repel(force=20,color="grey20",size=3,point.padding = 0.5,hjust = 0.5,
arrow = arrow(length = unit(0.01, "npc"), type = "open", ends = "last"),
segment.color="grey20",segment.size=0.2,segment.alpha=0.8,nudge_y=1)

p3


关于为线段添加“箭头”,这里主要用到grid::arrow()函数,注意,它的参数只适于调整“整支箭的箭头”部分,如下:
angle: 箭头的尖角的角度;
length: 箭头尖角的长度;
ends: "last", "first", "both", 指定线段的那端画箭头;
type: "open"和"closed" 指定箭头是否为封闭的三角形。

然后应用自定义主题,调整纵轴范围、散点颜色、图表主题等。

[AppleScript] 纯文本查看 复制代码
p3 + scale_y_continuous(breaks = c(0, 3, 6, 9, 12),limits = c(0, 12)) +
xlab("Average expression") +
ylab("Standardized variance") +
scale_color_manual(values=c("#a2a9af", "#a8df65")) +
theme_classic()+
theme(plot.margin = unit(c(1,1,0.5,0.5),"cm"),
legend.position = "none",
axis.title = element_text(size = rel(1.2)),
axis.text = element_text(size=rel(1)),
axis.line = element_line(size = 0.5, colour = "grey30"))


效果如下:


分组标记

上面的图表添加上箭头指引线,瞬间觉得最常见的散点图也变得“高大上”起来了呢。但对于“审美强迫症”来说,这些标签的排列还是有点乱,如何把他们排整齐呢?

下面就增加点难度,以图表的中轴线为界,把两侧的标签整齐排列。具体实现方法就是根据横坐标将数据集分成两部分,分别指定标签的偏移距离和排列方式。比如这里以“0”为分界,使用subset()函数将数据框分成两部分,分两次添加文字标签。

[AppleScript] 纯文本查看 复制代码
p4 <- ggplot(data = var.genes,aes(log10(vst.mean),vst.variance.standardized,
color=vst.variable,label=labels)) +
geom_point() +
geom_text_repel(
data = subset(var.genes, log10(vst.mean) >= 0),
nudge_x = 3 - log10(subset(var.genes, log10(vst.mean) >= 0)$vst.mean),
color = "grey20",
point.padding = NA,
size = 3,
segment.size = 0.2,
segment.color = "grey50",
direction = "y",
hjust = 1
) +
geom_text_repel(
data = subset(var.genes, log10(vst.mean) < 0),
nudge_x = -3 - log10(subset(var.genes, log10(vst.mean) < 0)$vst.mean),
color = "grey20",
point.padding = NA,
size = 3,
segment.size = 0.2,
segment.color = "grey50",
direction = "y",
hjust = 0
) +
scale_x_continuous(
breaks = c(-3, -2, -1, 0, 1,2,3),
limits = c(-3.5, 3.5))
p4


这里较难理解一点的是nudge_x(“标签”到“点”的水平距离)的设置,要想标签垂直对齐排列,需要为标签指定同样的横坐标,如本文的-3和3,只要用-3和3分别减去“点”的横坐标值就是对应的nudge_x值啦!当然这里的hjust参数也很重要,“0”表示文字左对齐,“0.5”表示文字居中,“1”表示文字右对齐。接着是图表的主题调整,方法同上。

[AppleScript] 纯文本查看 复制代码
p4 + scale_y_continuous(breaks = c(0, 3, 6, 9, 12),limits = c(0, 12)) +
xlab("Average expression") +
ylab("Standardized variance") +
scale_color_manual(values=c("#a2a9af", "#a8df65")) +
theme_classic()+
theme(plot.margin = unit(c(1,1,0.5,0.5),"cm"),
legend.position = "none",
axis.title = element_text(size = rel(1.2)),
axis.text = element_text(size=rel(1)),
axis.line = element_line(size = 0.5, colour = "grey30"))


如果觉得纯文字标签逼格还不够,我们还可以用圆角矩形标签的方式展示,这时候我们就用到了geom_label_repel()函数,参数与上文几乎一样,只需做简单调整。主要是通过fill参数调整矩形标签的颜色,其他不变。

p5 <- ggplot(data = var.genes,aes(log10(vst.mean),vst.variance.standardized,
color=vst.variable,label=labels)) +
geom_point() +
[AppleScript] 纯文本查看 复制代码
geom_label_repel(
data = subset(var.genes, log10(vst.mean) >= 0),
nudge_x = 3 - log10(subset(var.genes, log10(vst.mean) >= 0)$vst.mean),
color = "white",
alpha = 0.9,
point.padding = 0.5,
size = 3,
fill = "#96C93D",
segment.size = 0.5,
segment.color = "grey50",
direction = "y",
hjust = 1
) +
geom_label_repel(
data = subset(var.genes, log10(vst.mean) < 0),
nudge_x = -3 - log10(subset(var.genes, log10(vst.mean) < 0)$vst.mean),
color = "white",
alpha = 0.9,
point.padding = 0.5,
size = 3,
fill = "#9881F5",
segment.size = 0.5,
segment.color = "grey50",
direction = "y",
hjust = 0
) +
scale_x_continuous(
breaks = c(-3, -2, -1, 0, 1,2,3),
limits = c(-3.5, 3.5))
p5


图表的主题调整同上。

[AppleScript] 纯文本查看 复制代码
p5 + scale_y_continuous(breaks = c(0, 3, 6, 9, 12),limits = c(0, 12)) +
xlab("Average expression") +
ylab("Standardized variance") +
scale_color_manual(values=c("#a2a9af", "#ff85cb")) +
theme_classic()+
theme(plot.margin = unit(c(1,1,0.5,0.5),"cm"),
legend.position = "none",
axis.title = element_text(size = rel(1.2)),
axis.text = element_text(size=rel(1)),
axis.line = element_line(size = 0.5, colour = "grey30"))


绘制效果如下:


是不是好看多了?至此,添加个性化的标签无需Ai(Illustrator)也能批量自动完成啦!今天的内容就先到这里啦~



本文作者:基迪奥-莫北



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
新的一天加油!
回复

使用道具 举报

中华鲟

Rank: 5Rank: 5

主题
0
注册时间
2017.6.6
在线时间
67 小时

灌水之王


发表于 2020.5.28 10:31:56 | 显示全部楼层
好看,带劲
新的一天加油!
回复

使用道具 举报

管理员

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

主题
200
注册时间
2017.7.3
在线时间
513 小时

活跃会员荣誉管理


发表于 2020.5.28 15:05:11 | 显示全部楼层
新的一天加油!
回复 支持 反对

使用道具 举报

帝王蝶

Rank: 4

主题
1
注册时间
2016.8.25
在线时间
46 小时

发表于 2020.5.28 22:06:00 | 显示全部楼层
实用!赞赞赞
新的一天加油!
回复 支持 反对

使用道具 举报

钵水母

Rank: 3Rank: 3

主题
0
注册时间
2019.5.22
在线时间
29 小时

发表于 2020.5.31 17:20:40 | 显示全部楼层
本帖最后由 xmjy 于 2020.5.31 17:24 编辑

你好:
为什么我的做到 如下步骤的时候

#追加标签列;
var.genes$labels <- ""
var.genes$labels[1:n] <- topn
head(var.genes,10)

添加的“labels”不是gene的字符串,而是数字。
求解!!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表