如何用Python Pandas按SKU和日期为CSV追加指定序列值列
解决方案:基于Pandas实现SKU+日期分组的XValue范围分配
核心需求拆解
- 分组依据:SKU + 日期,每组内独立生成数值序列,跨组(不同日期/SKU)重置起始值
- 数值分配规则:
- 同一组内按指定范围的未使用数值依次递增
- 支持不同SKU对应不同数值范围
- 支持部分SKU按奇偶间隔选取数值(如仅取奇数/偶数)
实现步骤与代码
1. 数据读取与预处理
假设输入CSV包含SKU、Date、XValue(待替换)、Range to be used(SKU对应的数值范围,格式如5-10),先读取并解析范围:
import pandas as pd # 读取CSV文件 df = pd.read_csv('your_file.csv') # 解析数值范围:拆分起始和结束值,转为整数 df[['range_start', 'range_end']] = df['Range to be used'].str.split('-', expand=True).astype(int) # 配置SKU的奇偶规则:1=仅取奇数,0=仅取偶数,None=全部数值 sku_parity_rule = {5678: 1, 3214: None} # 可根据实际需求修改 df['parity'] = df['SKU'].map(sku_parity_rule)
2. 自定义分组分配函数
编写函数为每个分组生成符合规则的数值序列:
def assign_xvalue(group): start = group['range_start'].iloc[0] end = group['range_end'].iloc[0] parity = group['parity'].iloc[0] # 根据奇偶规则生成候选数值列表 if parity == 1: # 生成奇数序列:起始为奇数则取奇,起始为偶则从下一个奇数开始 candidates = list(range(start if start % 2 == 1 else start+1, end+1, 2)) elif parity == 0: # 生成偶数序列:起始为偶数则取偶,起始为奇则从下一个偶数开始 candidates = list(range(start if start % 2 == 0 else start+1, end+1, 2)) else: candidates = list(range(start, end+1)) # 无奇偶限制,取全部数值 # 为分组内每一行分配值,若行数超过候选数则循环使用 group_size = len(group) assigned_values = [candidates[i % len(candidates)] for i in range(group_size)] group['XValue'] = assigned_values return group
3. 分组应用函数并输出结果
按SKU和Date分组,应用分配函数后整理输出:
# 按SKU+日期分组,应用分配逻辑 result_df = df.groupby(['SKU', 'Date'], group_keys=False).apply(assign_xvalue) # 保留需要的输出列 result_df = result_df[['SKU', 'Date', 'XValue']] # 保存结果到CSV result_df.to_csv('output_file.csv', index=False) # 打印结果示例 print(result_df)
示例验证
单SKU示例
输入数据:
| SKU | Date | XValue | Range to be used |
|---|---|---|---|
| 5678 | 03/13/23 | 2 | 5-10 |
| 5678 | 03/13/23 | 2 | 5-10 |
| 5678 | 03/14/23 | 2 | 5-10 |
输出结果:
| SKU | Date | XValue |
|---|---|---|
| 5678 | 03/13/23 | 5 |
| 5678 | 03/13/23 | 6 |
| 5678 | 03/14/23 | 5 |
多SKU示例
输入数据:
| SKU | Date | Xvalue | Range to be used |
|---|---|---|---|
| 5678 | 03/13/23 | 2 | 5-10 |
| 3214 | 03/13/23 | 4 | 85-95 |
输出结果:
| SKU | Date | Xvalue |
|---|---|---|
| 5678 | 03/13/23 | 5 |
| 3214 | 03/13/23 | 85 |
奇偶间隔示例(SKU=5678取奇数)
输入数据:
| SKU | Date | XValue | Range to be used |
|---|---|---|---|
| 5678 | 03/13/23 | 2 | 5-10 |
| 5678 | 03/13/23 | 2 | 5-10 |
| 5678 | 03/13/23 | 2 | 5-10 |
输出结果:
| SKU | Date | XValue |
|---|---|---|
| 5678 | 03/13/23 | 5 |
| 5678 | 03/13/23 | 7 |
| 5678 | 03/13/23 | 9 |
注意事项
- 若分组内行数超过候选数值数量,代码会循环使用候选值,可根据需求修改为抛出警告或停止分配
- 建议先将日期列转为
datetime类型,避免格式问题导致分组错误:df['Date'] = pd.to_datetime(df['Date']) - 奇偶规则可灵活调整,比如修改
range的起始参数适配不同需求
内容的提问来源于stack exchange,提问作者Trevor
相关产品推荐
相关产品推荐

