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

如何在R中拟合仅含一个拐点的loess模型?若无法实现该如何近似?

带单拐点约束的Loess模型拟合方案

标准loess模型没法直接加「仅一个拐点」的约束——因为它是局部加权多项式回归,拟合过程是自适应局部调整的,天生可能产生多个拐点。下面是几个靠谱的近似方案:

1. 分段线性回归(严格单拐点)

直接拟合两段线性模型,拐点位置可以手动指定或者让模型自动估计,用segmented包就能实现:

library(segmented)
library(ggplot2)
library(dplyr)

# 先拟合基础线性模型
lm_fit <- lm(val ~ testage, data = df, weights = n)
# 拟合分段模型,psi参数给拐点的初始猜测(比如25)
seg_fit <- segmented(lm_fit, seg.Z = ~testage, psi = list(testage = 25))

# 生成预测数据
pred_df <- data.frame(testage = seq(0, 70, 1))
pred_df$val <- predict(seg_fit, newdata = pred_df)

# 绘图展示
df %>%
  ggplot(aes(x=testage, y=val, weight=n)) +
  geom_point() +
  scale_x_continuous(name = 'Age', limits = c(0,70)) +
  scale_y_continuous(limits = c(-6,0.8), name = expression(paste("Avg. ",theta))) +
  geom_line(data = pred_df, color="blue", size=1) +
  geom_hline(yintercept=0) +
  geom_vline(xintercept=0)

这个方法能严格保证只有一个拐点,拐点的位置会由模型根据数据优化出来。

2. 约束样条回归(平滑且限拐点)

用mgcv包的GAM模型,通过控制样条自由度来限制拐点数量。比如设置自由度k=3的立方样条,最多只会有1个拐点:

library(mgcv)

# 拟合约束GAM模型
gam_fit <- gam(val ~ s(testage, k=3), data = df, weights = n, method = "REML")

# 生成预测值
pred_df$gam_val <- predict(gam_fit, newdata = pred_df)

# 绘图
df %>%
  ggplot(aes(x=testage, y=val, weight=n)) +
  geom_point() +
  scale_x_continuous(name = 'Age', limits = c(0,70)) +
  scale_y_continuous(limits = c(-6,0.8), name = expression(paste("Avg. ",theta))) +
  geom_line(data = pred_df, aes(y=gam_val), color="red", size=1) +
  geom_hline(yintercept=0) +
  geom_vline(xintercept=0)

这种方案比分段线性更平滑,同时能控制拐点数量,适合需要曲线光滑度的场景。

3. 分段非线性模型(适配趋势)

如果你的数据是先升后降(或反之)的趋势,可以拟合分段二次模型,确保只有一个拐点:

# 拟合分段二次模型,start参数给初始值
nls_fit <- nls(val ~ a + b*testage + d*pmax(testage - c, 0)^2, 
               data = df, 
               weights = n,
               start = list(a=-6, b=0.3, c=25, d=-0.01))

# 生成预测值
pred_df$nls_val <- predict(nls_fit, newdata = pred_df)

# 绘图
df %>%
  ggplot(aes(x=testage, y=val, weight=n)) +
  geom_point() +
  scale_x_continuous(name = 'Age', limits = c(0,70)) +
  scale_y_continuous(limits = c(-6,0.8), name = expression(paste("Avg. ",theta))) +
  geom_line(data = pred_df, aes(y=nls_val), color="green", size=1) +
  geom_hline(yintercept=0) +
  geom_vline(xintercept=0)

这里的拐点c是模型的估计参数,曲线在拐点前后的趋势可以灵活调整,适配数据的实际形态。

总结

如果必须严格保证只有一个拐点,分段线性/非线性回归是最直接的选择;如果想要平滑曲线同时限制拐点,约束样条GAM更合适——这两种方案都比单纯调大loess的span更精准地满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:05:08