如何在pandas中创建自定义dekad频率以适配statsmodels时序预测需求
Pandas自定义dekad(旬)频率适配Statsmodels预测方案
方法1:注册全局自定义频率类(推荐)
通过继承Pandas的DateOffset类并注册,可以实现原生支持dekad频率的所有操作,包括生成序列、重采样、频率赋值等。
import pandas as pd from pandas.tseries.offsets import DateOffset, MonthEnd from pandas.tseries.frequencies import register_offset class Dekad(DateOffset): _attributes = ["n"] def apply(self, dt): n = self.n # 计算当前日期所属旬位 if dt.day <= 10: curr_dekad = 1 elif dt.day <= 20: curr_dekad = 2 else: curr_dekad = 3 # 换算总旬数计算偏移后位置 total_dekad = (dt.year - 1) * 36 + (dt.month - 1) * 3 + curr_dekad + n - 1 target_year = total_dekad // 36 + 1 remaining = total_dekad % 36 target_month = remaining // 3 + 1 target_dekad = remaining % 3 + 1 # 生成目标日期,自动处理大小月、闰年 if target_dekad == 1: return pd.Timestamp(year=target_year, month=target_month, day=10) elif target_dekad == 2: return pd.Timestamp(year=target_year, month=target_month, day=20) else: return pd.Timestamp(year=target_year, month=target_month, day=1) + MonthEnd(1) # 注册频率,别名为Dkd,避免和日频率D冲突 register_offset(Dekad, "Dkd")
注册完成后即可像原生频率一样使用:
- 生成连续dekad时间序列:
pd.date_range(start="2020-01-10", end="2023-12-31", freq="Dkd") - 给现有时间索引赋值频率:
df.index = df.index.asfreq("Dkd")
方法2:临时适配方案(无需注册全局频率)
如果不想修改全局频率配置,可以直接手动为合法的dekad索引赋值频率属性,满足Statsmodels的入参要求:
- 先验证现有索引是否完全符合dekad间隔规则
def validate_dekad_index(idx): expected_idx = pd.date_range(start=idx[0], periods=len(idx), freq=Dekad(1)) return all(idx == expected_idx)
- 验证通过后直接赋值频率:
# 确认索引无缺失后执行 df.index.freq = Dekad(1)
适配效果验证
训练HoltWinters模型时可以通过以下代码确认频率被正确识别:
from statsmodels.tsa.holtwinters import ExponentialSmoothing model = ExponentialSmoothing(df, freq="Dkd") print(model.freq) # 输出<Dekad>即代表识别成功
注意:如果原始索引存在缺失的dekad节点,
asfreq方法会自动补全缺失位置并赋值NaN,可根据业务需要选择填充缺失值或清洗异常节点后再训练模型。
内容的提问来源于stack exchange,提问作者Tommy Lees
相关产品推荐
相关产品推荐

