基于Pandas计算DataFrame日期区间内的节假日天数
正确计算日期区间内节假日天数的Pandas实现
初始数据表
| num_ID | start_date | end_date | time |
|---|---|---|---|
| 1 | 2022-02-10 | 2022-02-11 | 0 days 09:23:00 |
| 1 | 2022-02-12 | 2022-02-15 | 2 days 12:23:00 |
| 2 | 2022-02-12 | 2022-02-15 | 2 days 10:23:00 |
| 2 | 2022-02-05 | 2022-02-27 | 22 days 02:35:00 |
| 3 | 2022-02-04 | 2022-02-06 | 1 days 19:55:00 |
| 3 | 2022-02-12 | 2022-02-15 | 2 days 05:21:00 |
| 3 | 2022-02-12 | 2022-02-15 | 2 days 05:15:00 |
节假日表
该表包含连续日期及节假日标记,省略行的is_holiday值均为False:
| date | is_holiday | name | other |
|---|---|---|---|
| 2022-01-01 | True | ABC | red |
| 2022-01-02 | False | CNA | blue |
| ... | ... | ... | ... |
| 2022-02-15 | True | OOO | red |
| 2022-02-16 | True | POO | red |
| 2022-02-17 | False | KTY | blue |
| ... | ... | ... | ... |
| 2023-12-30 | False | TTE | white |
| 2023-12-31 | True | VVV | red |
需求
为初始数据表新增total_days列,统计每行start_date至end_date区间内(包含两端日期),节假日表中is_holiday=True的总天数。此前的方案存在计算错误,以下是正确实现方法。
实现代码
import pandas as pd # 初始化初始数据表(实际场景可直接读取已有数据) df_initial = pd.DataFrame({ 'num_ID': [1,1,2,2,3,3,3], 'start_date': ['2022-02-10','2022-02-12','2022-02-12','2022-02-05','2022-02-04','2022-02-12','2022-02-12'], 'end_date': ['2022-02-11','2022-02-15','2022-02-15','2022-02-27','2022-02-06','2022-02-15','2022-02-15'], 'time': ['0 days 09:23:00','2 days 12:23:00','2 days 10:23:00','22 days 02:35:00','1 days 19:55:00','2 days 05:21:00','2 days 05:15:00'] }) # 初始化节假日表(实际场景可直接读取已有数据) df_holidays = pd.DataFrame({ 'date': ['2022-01-01','2022-01-02','2022-02-15','2022-02-16','2022-02-17','2023-12-30','2023-12-31'], 'is_holiday': [True, False, True, True, False, False, True], 'name': ['ABC','CNA','OOO','POO','KTY','TTE','VVV'], 'other': ['red','blue','red','red','blue','white','red'] }) # 1. 转换日期列为datetime类型,确保日期格式统一 df_initial['start_date'] = pd.to_datetime(df_initial['start_date']) df_initial['end_date'] = pd.to_datetime(df_initial['end_date']) df_holidays['date'] = pd.to_datetime(df_holidays['date']) # 2. 提取所有节假日日期存入集合,提升查询效率 holiday_set = set(df_holidays.loc[df_holidays['is_holiday'], 'date']) # 3. 定义函数计算单一行的节假日天数 def calc_holiday_count(row): # 生成区间内所有日期(包含起始和结束日期) date_range = pd.date_range(start=row['start_date'], end=row['end_date'], inclusive='both') # 统计落在节假日集合中的日期数量 return sum(1 for dt in date_range if dt in holiday_set) # 4. 应用函数生成total_days列 df_initial['total_days'] = df_initial.apply(calc_holiday_count, axis=1) # 输出结果 print(df_initial)
代码说明
- 日期类型转换:确保两个表的日期列都是
datetime类型,避免字符串匹配错误。 - 集合存储节假日:集合的查询时间复杂度为O(1),比遍历DataFrame效率更高,适合数据量较大的场景。
- 精确日期区间生成:用
pd.date_range生成包含两端的完整日期序列,确保每个日期都被检查,避免仅通过天数差计算导致的误差。
预期结果示例
以初始数据表前两行为例:
- 第一行区间
2022-02-10至2022-02-11无节假日,total_days=0 - 第二行区间
2022-02-12至2022-02-15包含节假日2022-02-15,total_days=1
内容的提问来源于stack exchange,提问作者Carola
相关产品推荐
相关产品推荐

