Pandas时间区间粒度转换性能优化求助
高效解决Pandas日期区间展开性能问题
原代码的性能瓶颈分析
你的代码运行极慢的核心原因有两个:
- 逐行循环(
iterrows()):Python层面的逐行处理完全没有利用Pandas的向量化优势,对于715K行的数据集来说,这种循环的开销极大。 - 频繁
append()操作:每次df2.append()都会创建新的DataFrame,涉及大量内存分配和数据复制,随着数据量增长,性能会呈指数级下降。
推荐的高效实现方法
以下两种方法均基于向量化操作,能将处理时间从数小时压缩到几分钟甚至更短。
方法1:apply + date_range + explode(简洁易读)
这是最直观的向量化实现,利用Pandas内置的日期生成和行展开功能:
import pandas as pd # 先确保日期列是datetime类型(仅需执行一次) df1['start'] = pd.to_datetime(df1['start']) df1['end'] = pd.to_datetime(df1['end']) # 对每行生成日期范围列表,再展开为单独行 df1['Date'] = df1.apply(lambda row: pd.date_range(row['start'], row['end'], freq='D'), axis=1) df2 = df1.explode('Date').drop(columns=['start', 'end'])
方法2:Numpy广播(极致性能)
如果追求最快速度,用Numpy的广播机制直接构造数据,避免apply的微小开销:
import pandas as pd import numpy as np # 转换日期列 df1['start'] = pd.to_datetime(df1['start']) df1['end'] = pd.to_datetime(df1['end']) # 计算每行需要展开的天数 df1['repeat_count'] = (df1['end'] - df1['start']).dt.days + 1 # 重复非日期列对应次数 non_date_cols = df1[['ColA', 'ColB', 'ColC']].values.repeat(df1['repeat_count'], axis=0) # 生成所有日期序列并拼接 date_sequences = np.concatenate( df1.apply(lambda row: pd.date_range(row['start'], row['end'], freq='D'), axis=1).values ) # 构造最终DataFrame df2 = pd.DataFrame(non_date_cols, columns=['ColA', 'ColB', 'ColC']) df2['Date'] = date_sequences
额外优化建议
- 内存管理:7150万行数据会占用大量内存(预计数GB),如果内存不足,可以将原数据集分块处理,每块处理后保存为CSV/Parquet文件,最后合并结果。
- 提前转换日期类型:原代码中每次循环都调用
pd.to_datetime(),这是不必要的重复操作,提前一次性转换能节省大量时间。
内容的提问来源于stack exchange,提问作者ImFabien75
相关产品推荐
相关产品推荐

