如何标记ggplot中method="gam"的geom_smooth曲线顶点
为GAM平滑曲线添加顶点标记、虚线及X轴值文本(分面场景)
核心思路
因为GAM是样条拟合模型,没法直接套用loess的顶点提取方案,所以我们需要按分组手动拟合GAM模型,提取所有拟合点后定位每个分组的顶点(y值最大的点),再将这些顶点数据作为额外图层添加到ggplot中。
完整代码示例
1. 数据准备(替换为你的真实数据集)
library(tidyverse) library(mgcv) # 模拟与你数据集结构一致的测试数据(替换成你的b数据集即可) set.seed(123) b <- expand.grid( vesicles = c("Vesicle1", "Vesicle2", "Vesicle3"), cohort = c("CohortA", "CohortB"), x = seq(0, 15, length.out = 60) ) %>% mutate( y = case_when( cohort == "CohortA" ~ 4 + 0.8*sin(x) + rnorm(n(), 0, 0.4), cohort == "CohortB" ~ 2 + 0.6*x - 0.03*x^2 + rnorm(n(), 0, 0.4) ) )
2. 提取GAM曲线的顶点数据
# 按vesicles和cohort分组,拟合GAM并提取顶点 peak_data <- b %>% group_by(vesicles, cohort) %>% nest() %>% mutate( # 针对每个分组拟合指定参数的GAM模型 gam_model = map(data, ~ gam(y ~ s(x, bs = "cs"), data = .x)), # 生成模型的拟合数据(包含x和预测y值) fitted_vals = map(gam_model, ~ tibble(x = .x$model$x, y_pred = predict(.x))), # 筛选出每个分组中y_pred最大的顶点 peak = map(fitted_vals, ~ .x %>% slice_max(y_pred, n = 1)) ) %>% unnest(peak) %>% select(vesicles, cohort, x_peak = x, y_peak = y_pred)
3. 绘制最终图表
ggplot(b, aes(x = x, y = y, color = cohort)) + # 原始数据点 geom_point(alpha = 0.5) + # 指定参数的GAM平滑曲线 geom_smooth(method = "gam", formula = y ~ s(x, bs = "cs"), se = FALSE) + # 添加顶点黑色标记点 geom_point(data = peak_data, aes(x = x_peak, y = y_peak), color = "black", size = 3) + # 添加顶点到x轴的黑色虚线 geom_segment( data = peak_data, aes(x = x_peak, xend = x_peak, y = 0, yend = y_peak), color = "black", linetype = "dashed" ) + # 添加顶点对应的x轴值文本(上方偏移避免遮挡) geom_text( data = peak_data, aes(x = x_peak, y = y_peak + 0.3, label = round(x_peak, 2)), color = "black", fontface = "bold" ) + # 按vesicles分面 facet_wrap(~ vesicles) + theme_bw()
关键细节说明
- 分组拟合逻辑:通过
group_by+nest+map实现每个vesicles+cohort组合单独拟合GAM,确保顶点提取的准确性。 - 顶点调整:如果需要找曲线最小值,将
slice_max(y_pred, n=1)替换为slice_min(y_pred, n=1)即可。 - 文本偏移:
y = y_peak + 0.3的偏移量可根据你的数据y轴范围自行调整,避免遮挡顶点。 - 变量对应:替换测试数据时,确保你的真实数据集
b中vesicles、cohort、x、y变量名与代码一致。
内容的提问来源于stack exchange,提问作者cmirian
相关产品推荐
相关产品推荐

