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

