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

R语言如何为分段geom_smooth曲线添加贴近曲线的标签并去除指引线

核心问题原因

你当前生成的标签贴近原始数据点,是因为geom_label_repel绑定的是原始数据的实测value,而非geom_smooth输出的拟合值,我们需要先提取平滑曲线的拟合结果再绑定标签。如果要去掉标签指引线,只需在geom_label_repel中设置segment.color = NA即可。

完整可运行代码

# 加载依赖包
library(tidyverse)
library(ggrepel)

# 示例数据
df <- structure(list(t = c(45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 
47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 
50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 
53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 
56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 59, 59, 59, 59, 
59, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 
63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65), 
    x = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), name = c("P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4", "P1", "P2", "P2+", "P3", "P4", "P1", "P2", 
    "P2+", "P3", "P4"), value = c(48L, 132L, 111L, 115L, 2L, 
    58L, 126L, 82L, 74L, 0L, 45L, 119L, 78L, 87L, 0L, 56L, 106L, 
    105L, 88L, 1L, 52L, 78L, 91L, 107L, 1L, 35L, 96L, 86L, 98L, 
    1L, 61L, 118L, 90L, 108L, 2L, 45L, 114L, 93L, 98L, 2L, 55L, 
    108L, 78L, 76L, 7L, 44L, 97L, 94L, 96L, 0L, 40L, 111L, 93L, 
    88L, 1L, 43L, 78L, 66L, 113L, 2L, 20L, 57L, 84L, 41L, 0L, 
    17L, 51L, 81L, 34L, 0L, 40L, 55L, 64L, 32L, 0L, 25L, 67L, 
    71L, 37L, 0L, 16L, 67L, 60L, 57L, 0L, 23L, 46L, 62L, 47L, 
    1L, 34L, 75L, 68L, 39L, 0L, 34L, 60L, 85L, 24L, 0L, 20L, 
    58L, 63L, 37L, 1L)), row.names = c(NA, -105L), class = c("tbl_df", 
"tbl", "data.frame"))

# 1. 先构建基础平滑图层,提取拟合数据
p_base <- df %>%
  ggplot(aes(x = t, y = value, color = name, group = interaction(x, name))) +
  geom_smooth(se = F, method = "loess")

# 2. 提取拟合结果并匹配回原始分组
smooth_data <- ggplot_build(p_base)$data[[1]] %>%
  left_join(
    df %>% distinct(group = group_indices(., interaction(x, name)), x, name),
    by = "group"
  )

# 3. 筛选每个分组首尾的拟合点作为标签锚点
smooth_label <- smooth_data %>%
  group_by(group) %>%
  filter(x == min(x) | x == max(x)) %>%
  mutate(label = name)

# 4. 最终绘图
ggplot() +
  geom_smooth(data = df, aes(x = t, y = value, color = name, group = interaction(x, name), shape = name), se = F) +
  geom_vline(xintercept = 57, linetype = "dashed", lwd = 0.3) +
  scale_color_discrete(guide = 'none') +
  # segment.color = NA 直接去掉指引线,标签锚点为拟合值,自然贴合平滑曲线
  geom_label_repel(data = smooth_label, aes(x = x, y = y, color = name, label = label), segment.color = NA)

可选调整

如果不需要左右两侧都显示标签,仅需要在曲线末尾显示,只需将第三步的筛选条件改为filter(x == max(x))即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:45:00