如何高效合并DataFrame匹配公司报表日对应的在职董事信息
性能问题核心原因
原方案采用按companyid直接左连接的逻辑,会生成笛卡尔积形式的中间表:如果某公司有N条月度报表记录、M条董事任职记录,中间表会生成N*M条冗余数据,700万行级别的数据量下会直接占满内存,无法完成计算。
优化方案
方案1:使用Polars条件连接(推荐,多董事场景兼容、性能最高)
Polars是基于Rust开发的高性能数据处理库,内置优化的条件连接逻辑,不会生成全量中间笛卡尔积,内存占用仅为Pandas的1/3左右,处理千万级数据仅需数分钟。
import pandas as pd import polars as pl # 第一步:统一转换所有日期列为datetime格式 df1['rdate'] = pd.to_datetime(df1['rdate']) df2['datestartrole'] = pd.to_datetime(df2['datestartrole']) df2['dateendrole'] = pd.to_datetime(df2['dateendrole']) # 第二步:转为Polars DataFrame pl_df1 = pl.from_pandas(df1) pl_df2 = pl.from_pandas(df2) # 第三步:按companyid关联后直接过滤在职条件 result_pl = pl_df1.join( pl_df2, on="companyid", how="left" ).filter( (pl.col("datestartrole") < pl.col("rdate")) & ((pl.col("dateendrole") > pl.col("rdate")) | pl.col("dateendrole").is_null()) ) # 第四步:转回Pandas格式(如果需要) result = result_pl.to_pandas()
方案2:Pandas分组处理(内存受限场景适用)
如果不想引入新库,可以按companyid分组逐批处理,避免一次性加载全量中间数据:
import pandas as pd # 统一转换日期格式 df1['rdate'] = pd.to_datetime(df1['rdate']) df2['datestartrole'] = pd.to_datetime(df2['datestartrole']) df2['dateendrole'] = pd.to_datetime(df2['dateendrole']) # 将董事表按companyid预分组为字典,加速查询 df2_grouped = dict(tuple(df2.groupby('companyid'))) result_list = [] # 逐公司处理月度报表 for companyid, report_group in df1.groupby('companyid'): # 跳过无董事记录的公司 if companyid not in df2_grouped: continue dir_records = df2_grouped[companyid] # 逐行匹配在职董事 for _, report_row in report_group.iterrows(): rdate = report_row['rdate'] active_dirs = dir_records[ (dir_records['datestartrole'] < rdate) & ((dir_records['dateendrole'] > rdate) | dir_records['dateendrole'].isna()) ] # 合并结果 for _, dir_row in active_dirs.iterrows(): merged_row = {**report_row.to_dict(), **dir_row.to_dict()} result_list.append(merged_row) result = pd.DataFrame(result_list)
额外优化技巧
- 提前删除df1、df2中不需要的字段,减少数据加载量
- 启用Pandas的PyArrow后端,进一步提升计算速度:
pd.options.mode.dtype_backend = 'pyarrow'
内容的提问来源于stack exchange,提问作者Gregi_G
相关产品推荐
相关产品推荐

