Python实现考虑多产品差异的pandas时间序列分组拆分
多产品不对齐时序的独立拆分方案
核心逻辑是放弃全局按统一日期阈值切分的思路,按产品维度分组后,对每个产品自身的时序序列独立执行切分,最后合并所有产品的切分结果,天然支持同一日期在不同产品下分属训练/测试集的需求,也完全适配各产品时序起止时间不对齐的场景。
具体实现步骤
- 先对数据集做排序,保证每个产品内部的记录严格按日期升序排列,避免时序乱序引发数据泄露
- 按
prod字段分组,逐组对单个产品的时序序列计算切分点 - 拆分每个组的训练、测试子集,分别存入列表
- 拼接所有组的子集,得到最终的全量训练集、测试集
代码示例
1. 预处理&样例数据构造
import pandas as pd # 构造和描述结构一致的样例数据 df = pd.DataFrame([ ["d1", "p1", 10], ["d1", "p2", 10], ["d2", "p1", 15], ["d2", "p2", 12], ["d3", "p1", 8], ["d3", "p2", 5], ["d3", "p3", 7], ["d4", "p2", 9], ["d4", "p3", 11], ["d4", "p4", 6], ["d5", "p2", 20], ["d5", "p3", 13], ["d5", "p4", 10] ], columns=["date", "prod", "value"]) # 按产品、日期升序排序,保证每个产品内部时序正确 df = df.sort_values(by=["prod", "date"]).reset_index(drop=True)
2. 按比例切分(常用场景:每个产品前80%时序做训练)
train_ratio = 0.8 # 单个产品的训练集占比 train_chunks = [] test_chunks = [] for _, group in df.groupby("prod", group_keys=False): split_pos = int(len(group) * train_ratio) train_chunks.append(group.iloc[:split_pos]) test_chunks.append(group.iloc[split_pos:]) train_df = pd.concat(train_chunks).reset_index(drop=True) test_df = pd.concat(test_chunks).reset_index(drop=True)
3. 按时间窗口切分(常用场景:每个产品最后N条/最后N天做测试)
test_window = 1 # 取每个产品自身最后1条时序记录作为测试集 train_chunks = [] test_chunks = [] for _, group in df.groupby("prod", group_keys=False): train_chunks.append(group.iloc[:-test_window]) test_chunks.append(group.iloc[-test_window:]) train_df = pd.concat(train_chunks).reset_index(drop=True) test_df = pd.concat(test_chunks).reset_index(drop=True)
结果验证
以上面窗口切分的代码为例,输出的切分结果完全符合需求:
- 产品p1共有d1、d2、d3三条记录,最后1条d3的记录划入测试集,前两条划入训练集
- 产品p4共有d4、d5两条记录,最后1条d5的记录划入测试集,d4的记录划入训练集
- 同一日期d3下,p1的d3记录属于测试集,p2、p3的d3记录属于训练集,不存在全局统一的日期切分点
注意事项
- 禁止使用带
shuffle=True的随机拆分方法,会打乱时序顺序造成未来数据泄露 - 如果日期列是标准datetime格式,也可以直接对单个产品组按日期阈值做筛选切分,逻辑和上述代码一致
- 如果需要做时序交叉验证,沿用分组逻辑即可:对每个产品的独立时序单独做滑窗切分,再把各产品对应折的训练、验证样本拼接,就能得到正确的交叉验证数据集
内容的提问来源于stack exchange,提问作者Fernando Quintino
相关产品推荐
相关产品推荐

