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
相关产品推荐
相关产品推荐

