多产品时间序列拆分的Python交叉验证实现方法
按日期分组的时间序列交叉验证实现
问题描述
现有如下时间序列数据:
index date id value 0 d1 a 10 1 d2 a 15 2 d2 b 20 3 d3 a 18 4 d3 b 19 5 d4 b 21 6 d4 c 25
需要按日期进行时间序列拆分,拆分规则为:
- train_1 = index[0], test_1 = index[1, 2]
- train_2 = index[0, 1, 2], test_2 = index[3, 4]
- 依此类推,训练集包含所有之前日期的行,测试集为下一个日期的所有行
希望将这种拆分方式应用到交叉验证中,实现类似如下的循环逻辑:
for train_idx, test_idx in split_indexes: model.fit(X.iloc[train_idx], y_tr.iloc[train_idx]) # 后续评估逻辑
实现方法
可以通过以下步骤快速实现:
按日期分组提取索引
先对数据按date列分组,获取每个日期对应的行索引列表,并确保日期按时间顺序排列:import pandas as pd # 加载数据(示例) df = pd.DataFrame({ 'date': ['d1', 'd2', 'd2', 'd3', 'd3', 'd4', 'd4'], 'id': ['a', 'a', 'b', 'a', 'b', 'b', 'c'], 'value': [10, 15, 20, 18, 19, 21, 25] }) # 按日期分组,得到每个日期对应的索引集合 date_groups = df.groupby('date').groups # 按时间顺序排序日期 sorted_dates = sorted(date_groups.keys())生成交叉验证拆分索引对
遍历排序后的日期,依次拼接训练集和测试集的索引:split_indexes = [] for i in range(len(sorted_dates) - 1): # 训练集:前i+1个日期的所有行索引 train_idx = [] for date in sorted_dates[:i+1]: train_idx.extend(date_groups[date]) # 测试集:下一个日期的所有行索引 test_idx = list(date_groups[sorted_dates[i+1]]) split_indexes.append((train_idx, test_idx))应用到交叉验证循环
直接使用生成的split_indexes进行模型训练与验证:# 假设X为特征矩阵,y_tr为目标变量 for train_idx, test_idx in split_indexes: X_train, X_test = X.iloc[train_idx], X.iloc[test_idx] y_train, y_test = y_tr.iloc[train_idx], y_tr.iloc[test_idx] model.fit(X_train, y_train) y_pred = model.predict(X_test) # 后续评估逻辑(如计算MAE、RMSE等指标)
额外说明
- 该方式严格遵循时间顺序,避免了时间序列任务中常见的数据泄露问题
- 如果需要调整训练集窗口(比如只保留最近N个日期的数据),只需修改训练集日期的切片范围,例如
train_dates = sorted_dates[max(0, i+1-N):i+1]
内容的提问来源于stack exchange,提问作者Fernando Quintino
相关产品推荐
相关产品推荐

