如何用statsmodels MSTL获取月内日期季节性指数?
如何用statsmodels的MSTL处理月内日期的季节性波动?
MSTL本身仅支持固定周期的季节性分解,而月份天数不固定(28/30/31天),无法直接定义统一的月内周期。针对你的需求,有三种可行方案:
方案1:将月内日期特征作为外生变量加入MSTL
把月内日期相关的特征(比如每月第几天、是否月初/月末)提取为外生变量,让MSTL在分解小时、周度季节成分的同时,纳入月内波动的影响。这种方法最贴合MSTL的模型逻辑。
示例代码:
import pandas as pd from statsmodels.tsa.seasonal import MSTL import matplotlib.pyplot as plt # 假设你的数据是带DatetimeIndex的DataFrame,目标列名为'target' # 提取月内日期特征 data['day_of_month'] = data.index.day # 标记月初(前3天)和月末(后3天) data['is_month_start'] = (data.index.day <= 3).astype(int) data['is_month_end'] = (data.index.day >= data.index.days_in_month - 2).astype(int) # 选择外生变量 exog_features = data[['day_of_month', 'is_month_start', 'is_month_end']] # 执行MSTL分解,传入外生变量 res = MSTL(data['target'], periods=(24, 24*7), exog=exog_features).fit() # 可视化分解结果 res.plot() plt.tight_layout() plt.show()
方案2:先MSTL分解,再单独提取月内波动指数
先完成小时、周度的MSTL分解,然后对剩余残差单独分析月内日期的影响,提取对应的季节性指数。这种方法灵活性高,不改动原有分解流程。
步骤与代码:
- 先执行基础MSTL分解:
res = MSTL(data['target'], periods=(24, 24*7)).fit()
- 计算去除趋势、小时/周度季节成分后的残差:
residual = data['target'] - res.trend - res.seasonal['seasonal_24'] - res.seasonal['seasonal_168']
- 按每月第几天统计平均残差,得到月内日期指数:
# 按日期分组计算平均残差,即月内各天的季节性指数 monthly_day_seasonal = residual.groupby(residual.index.day).mean() # 可以将该指数合并回原数据,得到完整的季节性分解结果
方案3:用固定天数近似月周期(不推荐)
如果对精度要求较低,可尝试用30天作为固定月周期(即24*30小时),但这种方法会因实际月份天数差异导致周期错位,分解结果存在偏差,仅适合应急场景。
示例代码:
res = MSTL(data['target'], periods=(24, 24*7, 24*30)).fit() res.plot() plt.tight_layout() plt.show()
总结
优先选择方案1或方案2:方案1将月内特征融入MSTL模型,结果更连贯;方案2分步处理,便于单独调整月内指数的计算逻辑。
内容的提问来源于stack exchange,提问作者Llosgfynydd
相关产品推荐
相关产品推荐

