1 min read

ggplot label placement

本文曾经发表在 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)
## 使用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多的时候也不能随便用。食之无味,弃之可惜。鸡肋啊~~