如何基于Pandas列中的日期区间计算各月份包含的天数
按月份拆分统计日期区间内的天数
我有一个包含begin_date(对应代码里的PTO_Start_Date)和end_date(对应PTO_End_Date)列的DataFrame,需要将日期区间内的天数拆分到对应的月份列中(比如Feb-2023、Mar-2023)。目前已能计算总天数,但不知道如何处理跨月的情况,同时希望将逐行生成日期序列的Series代码改成Pandas列级别的实现。
现有代码
df['PTO_End_Date'] = pd.to_datetime(df.PTO_End_Date) df['PTO_Start_Date'] = pd.to_datetime(df.PTO_Start_Date) df['Days'] = (df['PTO_End_Date'] - df['PTO_Start_Date']).dt.days df['Feb-2023'] = df['Mar-2023'] = df['Apr-2023'] =
需要转换的Series代码(逐行生成日期序列)
s = pd.Series(index=pd.date_range(df['PTO_Start_Date'], df['PTO_End_Date']), dtype='float64')
解决方案
1. 计算单一行在指定月份的天数
先定义一个工具函数,用于计算单个日期区间在目标月份的有效天数:
def days_in_month(start_date, end_date, target_month): # 转换目标月份为当月起始和下月起始 month_start = pd.to_datetime(target_month) month_end = month_start + pd.offsets.MonthBegin(1) # 取日期区间与目标月份的交集起止 actual_start = max(start_date, month_start) actual_end = min(end_date, month_end) # 若交集有效则返回天数,否则返回0 return max((actual_end - actual_start).days, 0)
2. 批量生成月份统计列
针对需要统计的月份,用apply逐行计算并生成对应列:
# 指定需要统计的月份列表 target_months = ['2023-02', '2023-03', '2023-04'] # 循环生成每个月份的统计列 for month in target_months: col_name = pd.to_datetime(month).strftime('%b-%Y') # 格式化为Feb-2023样式 df[col_name] = df.apply( lambda row: days_in_month(row['PTO_Start_Date'], row['PTO_End_Date'], month), axis=1 )
3. 高效替代逐行生成Series的方法
如果需要生成每行的日期序列并自动统计各月份天数,用explode结合分组统计的方法更高效,避免逐行创建Series:
# 为每行生成日期范围列表 df['date_range'] = df.apply( lambda row: pd.date_range(row['PTO_Start_Date'], row['PTO_End_Date'], freq='D'), axis=1 ) # 展开日期列表为单行单日期的格式 expanded_df = df.explode('date_range') # 按原行索引和月份分组,统计每个区间在各月份的天数 monthly_counts = expanded_df.groupby( [expanded_df.index, expanded_df['date_range'].dt.to_period('M')] ).size().unstack(fill_value=0) # 将统计结果合并回原DataFrame,并重命名列名为Feb-2023样式 df = df.join(monthly_counts.rename(columns=lambda x: x.strftime('%b-%Y')))
内容的提问来源于stack exchange,提问作者Arthur D. Howland
相关产品推荐
相关产品推荐

