如何在Python中通过自定义字典为DataFrame添加周数列
问题场景与需求
现有指定结构的DataFrame(df),需通过自定义的weeks字典,根据day列的值映射对应的周数,并新增week列。此前编写的函数触发ValueError: Week number not found in dictionary错误,需修复实现该功能。
示例数据
- 原始DataFrame:
import pandas as pd df = pd.DataFrame({ 'day': ['2023-01-02', '2023-01-08', '2023-01-15', '2023-01-22', '2022-12-30'] })
- 自定义周数字典:
weeks = { '2023-01-01': 1, '2023-01-08': 2, '2023-01-15': 3, '2023-01-22': 4 }
- 预期结果:
| day | week |
|---|---|
| 2023-01-02 | 1 |
| 2023-01-08 | 2 |
| 2023-01-15 | 3 |
| 2023-01-22 | 4 |
| 2022-12-30 | 0 |
报错的尝试代码
def get_week(day): for start_day, week_num in weeks.items(): if day >= start_day: return week_num raise ValueError("Week number not found in dictionary") df['week'] = df['day'].apply(get_week)
解决方案
错误原因
报错是因为存在day值不满足遍历中的day >= start_day条件(比如示例中的2022-12-30早于所有字典内的起始日期),触发了手动抛出的异常。此外,字典遍历顺序不确定,可能导致匹配逻辑错误。
方法1:调整映射逻辑,处理边界值
先将日期统一转为datetime类型,再按起始日期排序后反向遍历,确保匹配到最接近的有效周数,同时处理边界情况:
# 转换day列为datetime类型 df['day'] = pd.to_datetime(df['day']) # 将weeks字典转换为按日期排序的列表 sorted_weeks = sorted((pd.to_datetime(date), num) for date, num in weeks.items()) def map_week(day): # 反向遍历,优先匹配最近的起始日期 for start_date, week_num in reversed(sorted_weeks): if day >= start_date: return week_num # 针对早于所有起始日期的情况,返回默认值(可按需调整) return 0 df['week'] = df['day'].apply(map_week)
方法2:使用pandascut函数高效实现
如果周起始日期是有序的,用pd.cut可以更简洁地完成区间映射:
df['day'] = pd.to_datetime(df['day']) # 提取排序后的日期边界和对应周数 sorted_dates = sorted(pd.to_datetime(date) for date in weeks.keys()) sorted_week_nums = [weeks[date.strftime('%Y-%m-%d')] for date in sorted_dates] # 添加最左边界,覆盖早于第一个起始日期的情况 sorted_dates.insert(0, pd.Timestamp.min) sorted_week_nums.insert(0, 0) # 用cut完成区间映射 df['week'] = pd.cut(df['day'], bins=sorted_dates, labels=sorted_week_nums, include_lowest=True)
验证结果
运行上述代码后,df将成功新增week列,所有day值都能匹配到对应的周数,不会触发异常。
内容的提问来源于stack exchange,提问作者user2100039
相关产品推荐
相关产品推荐

