Pandas实现:填充起始月至终止月间的月度报表(不含终止月)
处理方法(适配百万级数据量)
针对百万级别的DataFrame,绝对不要用循环,效率会极低。用Pandas的矢量化操作+日期序列生成+展开的方式,能高效完成需求:
步骤1:准备数据与日期格式转换
首先把原始的月份字符串转成Pandas可处理的datetime类型,统一为当月第一天:
import pandas as pd # 假设你的原始数据已经读入为df df = pd.DataFrame({ 'contract': ['Id1', 'Id2'], 'start month': ['Jan 2023', 'Feb 2023'], 'break month': ['Apr 2023', 'Feb 2023'] }) # 转换日期列,解析"Jan 2023"格式为datetime df['start_dt'] = pd.to_datetime(df['start month'], format='%b %Y') df['break_dt'] = pd.to_datetime(df['break month'], format='%b %Y')
步骤2:生成月份序列并展开
利用pd.date_range生成每个合同对应的月份区间(包含起始月、不含终止月),再用explode把序列拆成单行:
# 为每个合同生成月份序列,仅保留起始月早于终止月的情况 df['report_dates'] = df.apply( lambda x: pd.date_range(start=x['start_dt'], end=x['break_dt'], freq='MS') if x['start_dt'] < x['break_dt'] else pd.Series(dtype='datetime64[ns]'), axis=1 ) # 展开序列并过滤空值(对应起始=终止的合同) expanded_df = df.explode('report_dates').dropna(subset=['report_dates'])
步骤3:整理输出格式
把日期转回要求的文本格式,添加flag列,保留需要的字段:
# 转换日期为"Jan 2023"格式 expanded_df['report date'] = expanded_df['report_dates'].dt.strftime('%b %Y') # 添加flag列 expanded_df['flag'] = 1 # 筛选最终需要的列并重置索引 final_df = expanded_df[['contract', 'report date', 'flag']].reset_index(drop=True)
最终输出
运行后final_df的结果就是你要的格式:
| contract | report date | flag |
|---|---|---|
| Id1 | Jan 2023 | 1 |
| Id1 | Feb 2023 | 1 |
| Id1 | Mar 2023 | 1 |
性能说明
这种方法完全基于Pandas的内置矢量化操作,避免了Python层面的循环,处理200万行数据的效率会比循环高几个数量级,能在合理时间内完成计算。
内容的提问来源于stack exchange,提问作者Aleksandr Veselov
相关产品推荐
相关产品推荐

