多峰非线性曲线拟合:红色曲线平滑为蓝色曲线的技术咨询
曲线平滑解决方案:保持位置与面积约束
多段小曲线拟合的可行性
完全可行,这是贴合原始曲线趋势同时控制平滑度的有效思路。通过分段拟合能精准匹配曲线的整体走向,避免移动平均带来的位置偏移问题;只要在拟合后对曲线做面积归一化处理,就能保证最终曲线下总面积维持100%。
Python实现方法
1. 三次B样条插值+面积归一化
利用scipy工具实现平滑插值,再通过缩放保证面积约束:
import numpy as np from scipy.interpolate import make_interp_spline from scipy.integrate import trapz # 替换为你的原始数据 x = np.array([1,2,3,4,5,6,7,8,9,10]) y = np.array([...]) # 红色曲线的纵坐标值 # 生成更密集的横坐标点,提升平滑曲线的精度 x_new = np.linspace(x.min(), x.max(), 1000) # 三次样条插值,k=3平衡平滑度与贴合度 spl = make_interp_spline(x, y, k=3) y_smooth = spl(x_new) # 计算初始平滑曲线的面积,再缩放至总面积100 area_initial = trapz(y_smooth, x_new) y_smooth_scaled = y_smooth * (100 / area_initial)
2. 局部加权回归(Lowess)+归一化
适合噪声较多的曲线,通过局部加权拟合保留趋势:
import numpy as np from statsmodels.nonparametric.smoothers_lowess import lowess from scipy.integrate import trapz x = np.array([...]) y = np.array([...]) # frac控制平滑程度,0.1~0.5之间调整,值越大越平滑 y_smooth = lowess(y, x, frac=0.2)[:, 1] # 面积归一化 area = trapz(y_smooth, x) y_smooth_scaled = y_smooth * (100 / area)
Excel实现方法
1. 分段多项式拟合+面积归一化
- 按曲线趋势将数据分成3-5段(选在趋势转折点处)
- 对每段数据使用
FORECAST.LINEAR或LINEST函数拟合曲线,得到每段的拟合值 - 用梯形法计算每段拟合曲线的面积:
(上点纵坐标+下点纵坐标)/2 * 横坐标差,累加得到总面积 - 将所有拟合纵坐标值乘以
100/总面积,完成归一化
2. 内置平滑线+手动归一化
- 插入散点图,添加原始数据系列
- 右键系列→「添加趋势线」,选择「多项式」(次数设为3-5,平衡平滑度与贴合度)
- 右键趋势线→「设置趋势线格式」→勾选「显示公式」,用公式计算所有横坐标对应的拟合值
- 用梯形法计算拟合曲线面积,再缩放纵坐标至总面积100%
核心注意点
- 所有方法的关键步骤都是先平滑,再归一化:先得到贴合趋势的平滑曲线,再通过缩放纵坐标保证面积为100%,避免平滑过程中破坏位置与面积约束
- 分段拟合时,分段点选在曲线趋势突变的位置,避免过度分段导致保留噪声
内容的提问来源于stack exchange,提问作者siva
相关产品推荐
相关产品推荐

