如何参考pandas DataFrame中指定工作日列完成日期偏移调整
问题需求
根据pandas DataFrame中的Unloading point列指定的工作日规则,调整Date列的日期,规则如下:
- 若
Unloading point有有效值,返回距离原日期最近的、属于指定星期范围的日期 - 若
Unloading point为空,原日期为周末时回滚到最近的周五,工作日保持不变
实现依赖
首先导入pandas库,并定义星期映射关系:
import pandas as pd # 星期映射对应pandas dt.weekday返回值:0=周一、1=周二、…、6=周日 week_map = { 'MON': 0, 'TUE': 1, 'WED': 2, 'THU': 3, 'FRI': 4, 'SAT': 5, 'SUN': 6 }
数据预处理
先将日期列转为pandas datetime类型,方便后续计算:
# 示例数据构造,你可以替换为自己的数据源读取代码 data = { 'Date': ['5/30/2021', '6/11/2021', '6/5/2021', '6/4/2021', '5/27/2021', '5/29/2021', '5/29/2021', '6/6/2021', '6/1/2021', '5/29/2021', '6/1/2021', '7/31/2021', '6/1/2021', '5/26/2021', '6/14/2021', '5/27/2021', '6/15/2021', '5/22/2021', '6/10/2021', '6/24/2021'], 'Unloading point': ['MON-TUE-WED-THU-FRI', 'MON-TUE-WED-THU-FRI', 'THU', 'THU', 'THU', 'THU', '', 'MON-TUE-WED-THU-FRI', '', 'TUE', '', 'THU', 'WED', 'WED', 'MON-TUE-WED-THU-FRI', 'MON-TUE-WED', 'MON-TUE-WED', 'TUE-WED', 'MON-TUE-WED', 'TUE-FRI'] } df = pd.DataFrame(data) # 转换日期格式,format参数根据你实际的日期字符串格式调整 df['Date'] = pd.to_datetime(df['Date'], format='%m/%d/%Y')
核心计算逻辑
定义行处理函数,逐行计算映射后的日期:
def map_workday(row): current_date = row['Date'] unload_rule = row['Unloading point'].strip() if pd.notna(row['Unloading point']) else '' # 无指定规则的情况:周末回滚到周五 if not unload_rule: week_day = current_date.weekday() if week_day == 5: # 周六 return current_date - pd.Timedelta(days=1) elif week_day == 6: # 周日 return current_date - pd.Timedelta(days=2) return current_date # 有指定规则的情况:匹配最近的允许星期 allowed_weekdays = set([week_map[item] for item in unload_rule.split('-')]) if current_date.weekday() in allowed_weekdays: return current_date # 最多前后查找7天覆盖全星期 for offset in range(1, 8): prev_day = current_date - pd.Timedelta(days=offset) prev_valid = prev_day.weekday() in allowed_weekdays next_day = current_date + pd.Timedelta(days=offset) next_valid = next_day.weekday() in allowed_weekdays if prev_valid and not next_valid: return prev_day if next_valid and not prev_valid: return next_day # 前后距离相等时优先返回靠前的日期,如需优先靠后交换return顺序即可 if prev_valid and next_valid: return prev_day
生成结果
将函数应用到DataFrame,生成最终日期:
df['adjusted_date'] = df.apply(map_workday, axis=1) # 转换为和示例一致的字符串格式输出 df['adjusted_date_str'] = df['adjusted_date'].dt.strftime('%-m/%-d/%Y')
注意事项
- 若你的原始日期格式不是
月/日/年,需要修改pd.to_datetime中的format参数匹配实际格式 - 若需要排除法定节假日,可在函数中添加节假日列表判断逻辑,遇到节假日继续往前/后查找即可
- 前后日期距离相等时,当前默认优先返回更早的日期,可根据需要调整
prev_valid and next_valid分支的返回值
内容的提问来源于stack exchange,提问作者SamirJ
相关产品推荐
相关产品推荐

