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

Pandas阶梯时间序列的平滑形态调整(需满足分组均值匹配与无间断要求)

Pandas阶梯时间序列的平滑形态调整(需满足分组均值匹配与无间断要求)

嗨,这个需求抓得很准——既要严格保证每个阶梯分组的均值和原始值对齐,又要曲线平滑无跳变,还要尽量保留形态因子的趋势,确实需要权衡一下实现方式。咱们先理清楚核心矛盾:你的第一次尝试用了分组全局缩放,虽然保证了均值,但分组边界处的缩放比例突变直接导致了间断,所以关键是要把“均值调整”做成平滑过渡的,而不是一刀切的比例。

核心需求优先级

  • 必须满足:每个labels分组的结果均值 = 对应step_series的均值
  • 必须满足:结果曲线平滑无间断
  • 尽量满足:保留shape因子的整体形态

第一次尝试的问题分析

你的思路方向是对的:先提取趋势,结合形态因子得到基准曲线,再通过分组缩放对齐均值。但问题出在分组缩放是全局的——每个分组用一个固定比例去乘,这就导致两个分组的边界处,曲线值会因为比例突变而跳变,直接破坏了平滑性。

解决方案:平滑的分组均值调整

我们换个思路:不给每个分组加固定比例,而是给基准曲线叠加一个平滑的调整项,这个调整项在每个分组内的均值刚好能让整个分组的均值对齐原始step值,同时在分组边界处保持连续平滑。

具体步骤如下:

  1. 构建足够平滑的基准曲线(基于你已有的趋势和形态因子)
  2. 计算每个分组的均值差:原始step均值与基准曲线在该分组的均值的差值
  3. 用平滑权重函数(比如sigmoid)生成调整项的权重,让调整在分组边界无缝过渡
  4. 叠加调整项到基准曲线,得到最终结果

代码实现

import numpy as np
import pandas as pd

# 加载你生成的原始数据
data = produce_data()

# 1. 生成基准平滑曲线(沿用你原来的逻辑)
data['predict_trend'] = data['step_series'].rolling(365*3, center=True).mean().bfill().ffill()
data['raw_prediction'] = (data['shape'] + 1) * data['predict_trend']

# 2. 计算每个分组的均值差
group_stats = data.groupby('labels').agg(
    target_mean=('step_series', 'mean'),
    base_mean=('raw_prediction', 'mean')
)
group_stats['delta'] = group_stats['target_mean'] - group_stats['base_mean']
data = data.join(group_stats[['delta']], on='labels')

# 3. 生成平滑过渡的调整权重:用sigmoid函数实现分组边界的无缝衔接
def generate_smooth_weights(group, transition_window=30):
    # 获取分组的时间边界
    group_start = group.index.min()
    group_end = group.index.max()
    # 计算每个时间点到边界的归一化距离
    dist_to_start = (group.index - group_start).days / transition_window
    dist_to_end = (group_end - group.index).days / transition_window
    # sigmoid函数生成权重:分组内部权重趋近于1,边界处平滑降到0
    weight_left = 1 / (1 + np.exp(-dist_to_start + 5))
    weight_right = 1 / (1 + np.exp(-dist_to_end + 5))
    # 合并两个方向的权重,保证分组内稳定、边界处平滑过渡
    return weight_left * weight_right

# 对每个分组计算平滑权重
data['adjust_weight'] = data.groupby('labels', group_keys=False).apply(generate_smooth_weights)

# 4. 计算平滑调整项并得到最终结果
# 先生成初始调整项,再归一化保证分组均值差刚好被抵消
data['adjust_term'] = data['adjust_weight'] * data['delta']
adjust_term_group_means = data.groupby('labels')['adjust_term'].mean()
data['adjust_term'] = data['adjust_term'] * (data['delta'] / data.join(adjust_term_group_means, on='labels')['adjust_term'])

# 最终平滑结果
data['smoothed_result'] = data['raw_prediction'] + data['adjust_term']

# 验证分组均值匹配(应该输出True)
mean_validation = data.groupby('labels').agg(
    step_mean=('step_series', 'mean'),
    result_mean=('smoothed_result', 'mean')
)
print("分组均值匹配验证:")
print(np.allclose(mean_validation['step_mean'], mean_validation['result_mean']))

# 可视化对比
data[['step_series', 'raw_prediction', 'smoothed_result']].plot(figsize=(12, 6))

方案说明

  • 均值匹配保障:通过计算分组均值差,并让调整项的均值刚好填补这个差值,严格满足了分组均值对齐的核心要求
  • 平滑无间断:sigmoid权重让调整项在分组边界处平滑过渡,不会出现跳变;基准曲线本身是平滑的,叠加后结果依然保持连续
  • 形态保留:基准曲线保留了shape因子的原始形态,调整项仅做局部平滑修正,不会破坏整体趋势

你可以调整transition_window参数控制过渡的平滑程度:值越小,过渡越陡峭;值越大,过渡越平缓,按需调整即可。

备注:内容来源于stack exchange,提问作者granddejeuner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:49