如何使用Pandas或Numpy按月份拆分DataFrame中的日期范围
按月份拆分跨月日期范围的DataFrame
我有一个包含事件(A、B、C)的DataFrame,每个事件对应一组开始日期和结束日期,需要将这些跨月的日期范围按所属月份拆分。
示例数据
import pandas as pd data = {'Name': ['A', 'B', 'C'], 'Start_time': ['2017-12-15', '2017-12-15', '2017-12-15'], 'End_time': ['2018-01-17', '2017-12-22', '2018-05-22']} df = pd.DataFrame(data)
原始DataFrame:
| Events | Start_date | End_date |
|---|---|---|
| A | 2017-12-15 | 2018-01-17 |
| B | 2017-12-15 | 2017-12-22 |
| C | 2017-12-15 | 2018-05-22 |
预期结果
拆分后的DataFrame:
| Events | Start_date | End_date |
|---|---|---|
| A | 2017-12-15 | 2017-12-31 |
| A | 2018-01-01 | 2018-01-17 |
| B | 2017-12-15 | 2017-12-22 |
| C | 2017-12-15 | 2017-12-31 |
| C | 2018-01-01 | 2018-01-31 |
| C | 2018-02-01 | 2018-02-28 |
| C | 2018-03-01 | 2018-03-31 |
| C | 2018-04-01 | 2018-04-30 |
| C | 2018-05-01 | 2018-05-22 |
解决方案
通过以下步骤实现拆分:
- 转换日期列为
datetime类型,方便日期运算 - 生成每个事件覆盖的所有月份的起始日期序列
- 对每个月份计算对应的实际起止日期(不超出原事件的时间范围)
- 展开结果并整理为最终DataFrame
代码实现
import pandas as pd from pandas.tseries.offsets import MonthEnd # 1. 转换日期格式为datetime df['Start_time'] = pd.to_datetime(df['Start_time']) df['End_time'] = pd.to_datetime(df['End_time']) # 2. 定义拆分函数:处理单条事件的跨月拆分 def split_monthly(row): # 获取事件覆盖的所有月份的第一天(freq='MS'表示每月起始) month_starts = pd.date_range(start=row['Start_time'].replace(day=1), end=row['End_time'], freq='MS') split_results = [] for month_start in month_starts: # 获取当月最后一天,自动适配不同月份的天数 month_end = month_start + MonthEnd(1) # 计算当前拆分段的实际起始/结束日期 actual_start = max(row['Start_time'], month_start) actual_end = min(row['End_time'], month_end) split_results.append({ 'Events': row['Name'], 'Start_date': actual_start, 'End_date': actual_end }) return split_results # 3. 应用函数并展开结果 result = df.apply(split_monthly, axis=1).explode() result = pd.DataFrame(result.tolist()).reset_index(drop=True) # 可选:将日期格式化为字符串 result['Start_date'] = result['Start_date'].dt.strftime('%Y-%m-%d') result['End_date'] = result['End_date'].dt.strftime('%Y-%m-%d') print(result)
代码说明
pd.date_range生成事件覆盖的所有月份的第一天,确保不遗漏任何中间月份MonthEnd(1)自动计算当月最后一天,无需手动处理2月、30天月份等特殊情况max/min函数保证拆分后的日期范围严格在原事件的起止时间内explode()将每个事件生成的拆分列表展开为独立行
内容的提问来源于stack exchange,提问作者Control Solution
相关产品推荐
相关产品推荐

