本文曾经发表在 biobabble 微信公众号 链接

ggplot在绘制label的时候很容易出现字体溢出,位置难以调整的问题。Y叔曾经在公众号上吐槽过。

实际上,标签如何在图片中展示,还真不是一个简单的问题。有一个领域“Automatic label placement”就是研究该问题的。

下面介绍一下如何处理这个标签定位的问题。

方法一:使用hjust,vjust,nudge_x,nudge_y等参数调整

我们从mpg数据集中提取10行数据画图,默认情况下是这样的情况。

mpg数据集是ggplot2自带的一个234行和11个变量的数据,包含了38种流行车型的燃油经济性数据。

包括:生产厂家(manufacturer),型号(model),发动机排量(displ,单位为L),生产年份(year),气缸数目(cyl),传动类型(trans),驱动类型(drv,f=前驱,r=后驱,4=四驱),每加仑燃油在城市和高速公路上的里程数(cty和hwy),汽油种类(fl)和汽车类型(class)等。

library(ggplot2)
## 生成数据集
set.seed(0)
df <- mpg[sample(nrow(mpg),10),]

## 发动机排量和良好路况情况下单位耗油所能行驶的里程数
ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model))

这种情况下,边缘的字符串会溢出。可以添加hjust="inward"来避免这一情况。

## hjust="inward"把左侧的label右对齐,右侧的label左对齐。
ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model),hjust="inward")

但是这种情形仍然会出现point和label重叠的情况。因此需要进一步调节。使用nudge_xnudge_y可以设置标签显示位置的微小偏移。

由于标签是水平显示的,左右两侧容易出现溢出,而竖直方向上则一般不会,所以我们将竖直方向设为居中,并微调-0.5,这样就可以保证标签显示比较正常了。

ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model),hjust="inward",vjust="center",nudge_y = -.5)

hjust, vjust = c(“left”,“right”,“center”,“inward”,“outward”); nudge_x, nudge_y = value.

如果在Y轴边缘有溢出的话,则在结合调整xlim,ylim可以解决。如下所示:

ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model),size=12,hjust="inward",vjust="center",nudge_y = -.5) + 
  xlim(c(0,8))

如上图所示,虽然确保了标签没有溢出,但是同时又会有标签重叠的情况。

也可以参考 vignette(“ggplot2-specs”) 中的部分内容。

实际上,标签如何在图片中展示,还真不是一个简单的问题。有一个领域“Automatic label placement”就是研究该问题的。

不过,有一些R包可以帮助我们解决这一难题。

方法二:ggrepel

ggrepel包就是为了处理ggplot label而开发的。

library(ggrepel)
## Warning: package 'ggrepel' was built under R version 4.3.3
## 使用geom_text_repel可以一步完成上面类似的操作
ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text_repel(aes(label=model))

更多信息,请参考ggrepel文档中的ggrepel examples

方法三:directlabels

directlabels则是另外一个选择。这个包不仅能够用于ggplot图,还可以用于latitice基础绘图系统。

## 安装和载入
# install.packages("directlabels")
library("directlabels")

## 看一下效果
ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_dl(aes(label=model),method = "smart.grid")

这个smart.grid方法特别适合于point作图中points非常多的情况,避免使用legend,让图片更美观更易读。

比较一下下面两幅图,显然后者更好。

## 使用legend和颜色
ggplot(mpg,aes(displ,hwy,color=class)) + 
  geom_point()
## 使用label和颜色
ggplot(mpg,aes(displ,hwy,color=class)) + 
  geom_point(show.legend=F) + 
  geom_dl(aes(label=class),method="smart.grid")

geom_dl这里有一个method参数,可以有“last.points”,“first.points”,“top.qp”,“first.qp”,“last.qp”,“smart.grid”等不同选择。针对不同的绘图类型会有不同的可选项。

不同作图类型可用的方法可以参见:http://directlabels.r-forge.r-project.org/docs/index.html

外:check_overlap

check_overlap也是ggplot2geom_text自带的一个小参数,可以避免label重叠。应用时,会依次检查后面的label是否与前面的重叠,有重叠的话,就不显示。

## df数据集含有mpg中的十行数据
ggplot(df,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model),check_overlap=T)
## mpg数据集含有234行数据
ggplot(mpg,aes(displ,hwy)) + 
  geom_point() + 
  geom_text(aes(label=model),check_overlap=T)

这个参数,label少的时候用不上,label多的时候也不能随便用。食之无味,弃之可惜。鸡肋啊~~

作者简介

Chun-Hui Gao is a Research Associate at Huazhong Agricultural University.

重复使用

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The source code is licensed under MIT. The full source is available at https://github.com/yihui/hugo-prose.

欢迎修订

如果您发现本文里含有任何错误(包括错别字和标点符号),欢迎在本站的 GitHub 项目里提交修订意见。

引用本文

如果您使用了本文的内容,请按照以下方式引用:

gaoch (2019). ggplot label placement. BIO-SPRING. /post/2019/07/17/ggplot-label-placement/

BibTeX citation

@misc{
  title = "ggplot label placement",
  author = "gaoch",
  year = "2019",
  journal = "BIO-SPRING",
  note = "/post/2019/07/17/ggplot-label-placement/"
}