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

如何在ggplot2的geom_smooth拟合曲线上高亮指定区间片段

实现geom_smooth全局拟合曲线指定区间高亮的方法

原有gghighlight方案不符合预期的核心原因:gghighlight会对geom_smooth层的输入数据做过滤,仅用筛选区间内的原始数据重新拟合曲线,而非基于全局拟合结果高亮对应片段,因此会出现高亮段和原曲线走势不一致的问题。

以下提供两种通用实现方案:

方案1:手动预计算全局拟合结果

可自主控制所有拟合参数,灵活性更高:

# 构造示例数据
Dates <- seq(as.POSIXct("2018-01-01 00:00:00"), as.POSIXct("2021-01-01 00:00:00"), by = "days")
values <- rnorm(length(Dates), 1000, 500)
df <- data.frame(Dates, values)

library(ggplot2)

# 全局拟合,和geom_smooth默认参数保持一致(默认n<1000时用loess拟合,span=0.75)
global_fit <- loess(values ~ as.numeric(Dates), data = df, span = 0.75)
# 生成所有日期对应的拟合值
df$fit <- predict(global_fit, newdata = df)

# 定义高亮区间
highlight_start <- as.POSIXct("2020-03-24 00:00:00")
highlight_end <- as.POSIXct("2020-04-14 00:00:00")

ggplot(data = df, aes(Dates, values)) +
  scale_x_datetime(breaks = scales::breaks_width("years"), date_labels = "%Y") +
  geom_point(alpha = 0.3) +
  # 底层绘制全局拟合线
  geom_line(aes(y = fit), color = "grey50", linewidth = 1) +
  # 叠加高亮区间的拟合线段
  geom_line(aes(y = fit), 
            data = ~subset(.x, Dates >= highlight_start & Dates <= highlight_end),
            color = "blue", linewidth = 1.5)

方案2:提取ggplot内置拟合数据

无需手动重复拟合,兼容geom_smooth所有拟合方法(lm/gam/loess等均可直接使用):

# 构造示例数据同上
Dates <- seq(as.POSIXct("2018-01-01 00:00:00"), as.POSIXct("2021-01-01 00:00:00"), by = "days")
values <- rnorm(length(Dates), 1000, 500)
df <- data.frame(Dates, values)

library(ggplot2)

# 先绘制基础图,包含原始散点和全局拟合线
p_base <- ggplot(data = df, aes(Dates, values)) +
  scale_x_datetime(breaks = scales::breaks_width("years"), date_labels = "%Y") +
  geom_point(alpha = 0.3) +
  geom_smooth(se = FALSE) # 可根据需求开启置信区间se=T

# 从ggplot构建结果中提取全局拟合的坐标数据
smooth_data <- ggplot_build(p_base)$data[[2]]
# 转换x轴为POSIXct格式,和原始数据时间维度匹配
smooth_data$x <- as.POSIXct(smooth_data$x, origin = "1970-01-01")

# 定义高亮区间
highlight_start <- as.POSIXct("2020-03-24 00:00:00")
highlight_end <- as.POSIXct("2020-04-14 00:00:00")

# 叠加高亮线段层
p_base +
  geom_line(data = subset(smooth_data, x >= highlight_start & x <= highlight_end),
            aes(x = x, y = y),
            color = "blue", linewidth = 1.5, inherit.aes = FALSE)

如果需要同时高亮置信区间,只需对提取的拟合数据中的ymin/ymax字段做同样的区间筛选,再叠加geom_ribbon层即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:15:03