ggplot label placement
<h1>背景</h1><p>ggplot2在绘制label的时候很容易出现字体溢出,位置难以调整的问题。</p>
<p>实际上,标签如何在图片中展示,还真不是一个简单的问题。有一个领域“Automatic label placement”就是研究该问题的。</p>
<p>下面介绍一下如何处理这个标签定位的问题。</p>
<h1>方法一:使用hjust,vjust,nudge_x,nudge_y等参数调整</h1>
<p>我们从mpg数据集中提取10行数据画图,默认情况下是这样的情况。</p>
<blockquote>
<p>mpg数据集是ggplot2自带的一个234行和11个变量的数据,包含了38种流行车型的燃油经济性数据。</p>
<p>包括:生产厂家(manufacturer),型号(model),发动机排量(displ,单位为L),生产年份(year),气缸数目(cyl),传动类型(trans),驱动类型(drv,f=前驱,r=后驱,4=四驱),每加仑燃油在城市和高速公路上的里程数(cty和hwy),汽油种类(fl)和汽车类型(class)等。</p>
</blockquote>
<pre><code>library(ggplot2)
# 生成数据集
set.seed(1234)
df <- mpg
# 发动机排量和良好路况情况下单位耗油所能行驶的里程数
ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model))
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5x4k9qbdkeeao7od.png" alt="" /><br />
这种情况下,边缘的字符串会溢出。可以添加 <code>hjust="inward"</code>来避免这一情况。</p>
<pre><code># hjust="inward"把左侧的label右对齐,右侧的label左对齐。
ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model),hjust="inward")
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5x5mseqvd0i439e9.png" alt="" /></p>
<p>但是这种情形仍然会出现point和label重叠的情况。因此需要进一步调节。使用 <code>nudge_x</code>和 <code>nudge_y</code>可以设置标签显示位置的微小偏移。</p>
<p>由于标签是水平显示的,左右两侧容易出现溢出,而竖直方向上则一般不会,所以我们将竖直方向设为居中,并微调-0.5,这样就可以保证标签显示比较正常了。</p>
<pre><code>ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model),hjust="inward",vjust="center",nudge_y = -.5,
angle = 15, # 将标签旋转一个小角度
size = 2 # 适当缩小字体大小
)
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xcj79c12ks3vql0e.png" alt="" /></p>
<blockquote>
<p>hjust, vjust = c(“left”,“right”,“center”,“inward”,“outward”);<br />
nudge_x, nudge_y = value.</p>
</blockquote>
<p>如果在Y轴边缘有溢出的话,则在结合调整xlim,ylim可以解决。如下所示:</p>
<pre><code>ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model),hjust="inward",vjust="center",nudge_y = -.5,
angle = 15, # 将标签旋转一个小角度
size = 2 # 适当缩小字体大小
) +
xlim(c(-1,8)) + ylim(c(10,40))
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xgpa5fh0dy405wkv.png" alt="" /></p>
<p>如上图所示,虽然确保了标签没有溢出,但是同时可能又会有标签重叠的情况。</p>
<p>实际上,标签如何在图片中展示,还真不是一个简单的问题。有一个领域“Automatic label placement”就是研究该问题的。</p>
<p>不过,有一些R包可以帮助我们解决这一难题。</p>
<h1>方法二:ggrepel</h1>
<p>ggrepel包就是为了处理ggplot label而开发的。</p>
<pre><code>library(ggrepel)
# 使用geom_text_repel可以一步完成上面类似的操作
ggplot(df,aes(displ,hwy)) +
geom_point()+
geom_text_repel(aes(label=model))
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xiia4rxxadi6i3f.png" alt="" /></p>
<blockquote>
<p>更多信息,请参考ggrepel文档中的ggrepel examples</p>
</blockquote>
<h1>方法三:directlabels</h1>
<p>directlabels则是另外一个选择。这个包不仅能够用于ggplot图,还可以用于latitice基础绘图系统。</p>
<pre><code>library(directlabels)
# 看一下效果
ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_dl(aes(label=model),method = "smart.grid")
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xke1b9own5mmbdh.png" alt="" /></p>
<p>这个smart.grid方法特别适合于point作图中points非常多的情况,避免使用legend,让图片更美观更易读。</p>
<p>比较一下下面两幅图,显然后者更好。</p>
<pre><code># 使用legend和颜色
ggplot(mpg,aes(displ,hwy,color=class)) +
geom_point()
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xlv9xyet01mswgca.png" alt="" /></p>
<pre><code># 使用label和颜色
ggplot(mpg,aes(displ,hwy,color=class)) +
geom_point(show.legend=F) +
geom_dl(aes(label=class),method="smart.grid")
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xnrmtv0dicmrdrhc.png" alt="" /></p>
<blockquote>
<p>geom_dl这里有一个method参数,可以有“last.points”,“first.points”,“top.qp”,“first.qp”,“last.qp”,“smart.grid”等不同选择。针对不同的绘图类型会有不同的可选项。</p>
</blockquote>
<h1>补充:check_overlap</h1>
<p><code>check_overlap</code>也是 <code>ggplot2</code>的 <code>geom_text</code>自带的一个小参数,可以避免label重叠。应用时,会依次检查后面的label是否与前面的重叠,有重叠的话,就不显示。</p>
<pre><code># df数据集含有mpg中的十行数据
ggplot(df,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model),check_overlap=T)
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xpppi2ry5opb09j7.png" alt="" /></p>
<pre><code># mpg数据集含有234行数据
ggplot(mpg,aes(displ,hwy)) +
geom_point() +
geom_text(aes(label=model),check_overlap=T)
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/19/mi5xqs4b0vzjklxl7unn.png" alt="" /></p>
<p>这个参数,label少的时候用不上,label多的时候也不能随便用。</p>
页:
[1]