You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ggplot2中ggrepel配合geom_smooth时如何为每个分组平滑曲线仅添加单个标签

问题背景

初始绘图代码如下:

ggplot(gapminder::gapminder,aes(x=year,y=lifeExp,label=continent,color=continent))+
geom_line(size=.1,alpha=.2)+
guides(color="none")+
theme_minimal()+
geom_smooth(aes(color=continent),se=F,method="loess")+
ggrepel::geom_label_repel(direction = "y",stat="smooth",nudge_x = 5)

运行代码得到的效果中,geom_label_repel会为每条平滑拟合曲线上的所有预测点重复添加标签,无法实现每个大洲仅对应1个曲线标签的需求;如果移除stat="smooth"参数,标签会直接打在原始数据的所有单独折线上,不符合标注平滑聚合曲线的预期。
初始运行效果参考:
结果示意图

调整方案

问题根源是stat="smooth"默认会为每条拟合曲线生成80个等距x点位的预测值,标签层默认会对所有生成的点位逐一添加标签。只要让标签层仅识别每条平滑曲线最右端(最大年份对应位置)的1个点位,就能实现单标签效果,不需要移除stat="smooth"参数。
调整后可直接运行的完整代码:

ggplot(gapminder::gapminder,aes(x=year,y=lifeExp,color=continent))+
  geom_line(size=.1,alpha=.2)+
  guides(color="none")+
  theme_minimal()+
  geom_smooth(aes(color=continent),se=F,method="loess")+
  ggrepel::geom_label_repel(
    # 核心:仅在每组拟合点的最大x值(最右端)位置显示大洲标签
    aes(label = after_stat(ifelse(x == max(x), as.character(continent), NA_character_))),
    direction = "y",
    stat = "smooth",
    method = "loess",
    se = FALSE,
    nudge_x = 5,
    na.rm = TRUE
  )

关键逻辑说明

  • 保留stat="smooth"及对应method="loess"参数,保证标签位置完全对齐loess平滑拟合曲线,不会偏移到原始个体折线上
  • 用after_stat()读取stat平滑计算后的内部变量,判断当前点位是否为分组内x值最大的最右端点位,仅在该点位返回大洲名称作为标签,其余点位标签设为空值
  • 加na.rm = TRUE自动过滤掉标签为空的点位,最终每个大洲仅保留1个标签
  • 保留nudge_x = 5将标签向右推到曲线外侧,避免标签和曲线重叠,ggrepel会自动生成标签到对应曲线的引导连线

内容的提问来源于stack exchange,提问作者Misha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:51:21