Python中嵌套循环的高效替代方案求助
优化嵌套循环,提升Pandas大数据处理效率
原代码的核心问题是嵌套循环+逐行append操作:
iterrows()遍历DataFrame是效率极低的逐行操作,3万行数据的遍历本身就很慢- 每次
append都会创建新的DataFrame,时间复杂度达到O(N*M)(N为日期数,M为数据行数),完全无法支撑3万行的规模
下面提供两种高效的替代方案,利用Pandas的向量化操作和批量处理能力,将时间复杂度降到线性级别。
方案一:笛卡尔积+向量化过滤
适合日期范围不大(比如几百天)的场景,逻辑简单直观:
import pandas as pd import datetime file = '..\\Extrato.xlsx' df = pd.read_excel(file) # columns: "key", "id", "expiration_date" # 统一日期格式为date类型,避免后续重复转换 df['expiration_date'] = df['expiration_date'].dt.date # 生成完整日期序列并转为DataFrame date_a = datetime.date(2022, 12, 1) date_z = datetime.date.today() dates_df = pd.DataFrame({ 'simulated_date': pd.date_range(end=date_z, start=date_a).date }) # 通过临时键实现笛卡尔积(所有行 × 所有日期) df['temp_key'] = 1 dates_df['temp_key'] = 1 cross_data = pd.merge(df, dates_df, on='temp_key').drop('temp_key', axis=1) # 向量化过滤符合条件的行 time_machine = cross_data[cross_data['expiration_date'] <= cross_data['simulated_date']].copy() # 添加状态列并调整列顺序 time_machine['status'] = 'ok' time_machine = time_machine[['key', 'id', 'simulated_date', 'status']]
优化点说明:
- 用
pd.date_range直接生成日期序列,比手动列表推导式更高效,且直接统一日期类型 - 笛卡尔积通过
merge实现,是Pandas内部优化的批量操作,远快于嵌套循环 - 布尔索引过滤是向量化操作,替代逐行判断,效率提升几个数量级
- 全程避免
append,直接从过滤结果生成最终DataFrame,内存占用更可控
方案二:按行生成有效日期范围(内存更优)
如果日期范围较大,笛卡尔积会产生过多中间数据,可采用此方案:只给每行生成符合条件的日期范围,再展开数据:
import pandas as pd import datetime file = '..\\Extrato.xlsx' df = pd.read_excel(file) df['expiration_date'] = df['expiration_date'].dt.date date_a = datetime.date(2022, 12, 1) date_z = datetime.date.today() # 为每行生成符合条件的日期序列 def get_valid_dates(row): # 起始日期取expiration_date和date_a的较大值 start = max(row['expiration_date'], date_a) if start > date_z: return [] # 生成从start到date_z的所有日期 return pd.date_range(start=start, end=date_z).date # 应用函数并展开日期列表 df['simulated_date'] = df.apply(get_valid_dates, axis=1) time_machine = df.explode('simulated_date').drop('expiration_date', axis=1) # 添加状态列并调整顺序 time_machine['status'] = 'ok' time_machine = time_machine[['key', 'id', 'simulated_date', 'status']]
优化点说明:
- 仅生成每行实际需要的日期,避免无效的日期匹配,内存占用远低于笛卡尔积方案
apply+explode都是Pandas优化后的操作,效率远高于嵌套循环- 逻辑更贴合业务需求:只保留
expiration_date <= simulated_date的有效组合
内容的提问来源于stack exchange,提问作者user21736172
相关产品推荐
相关产品推荐

