Python DataFrame跨行列聚合处理速度慢的优化咨询
DataFrame按Name聚合并拼接字段性能优化方案
需求说明
- 待处理数据为20225行×7列的结构化表,重复行判定规则为
Name字段取值一致 - 聚合规则:
- 同一
Name对应的所有行中,3个邮箱列(People1.Email/People2.Email/People3.Email)的非空值拼接为单个字符串,自动剔除null值 - 同一
Name对应的所有行中,3个公司名列(People1.CompanyName/People2.CompanyName/People3.CompanyName)的非空值拼接为单个字符串,自动剔除null值
- 同一
- 最终输出20106行×3列的新表,每个
Name对应唯一一行,三列分别为Name、拼接后的邮箱字符串、拼接后的公司名字符串 - 原逻辑可正常输出结果,但运行耗时约6分钟,存在较大优化空间
原代码性能问题
- 采用逐Name循环的写法,每次循环需要执行6次全表扫描匹配对应Name的行,2万余条Name对应12万次全表查询,IO开销极高
- 循环内反复调用
pd.concat逐行拼接结果表,pandas每次concat都会复制全量结果生成新对象,数据量越大拼接开销呈指数级增长 - 全部聚合逻辑用纯Python列表推导实现,没有利用pandas底层C实现的向量化运算能力,执行效率低
优化后实现代码
全程使用pandas内置的分组聚合能力,无显式Python层循环,2万行数据处理耗时可压缩至1秒以内:
import pandas as pd import time print(time.strftime("%H:%M:%S", time.localtime()) + " start") # 读取Excel文件 df = pd.read_excel(r'C:\sample.xlsx', sheet_name=0) # 自动识别所有邮箱列、公司名列 email_columns = [col for col in df.columns if col.endswith('.Email')] company_columns = [col for col in df.columns if col.endswith('.CompanyName')] # 按Name分组聚合 df_new = df.groupby('Name', as_index=False).apply( lambda group: pd.Series({ # 组内所有邮箱列打平、去空、拼接,分隔符按需替换,原逻辑用空格就把';'改成' ' 'Emails': ';'.join(group[email_columns].stack().dropna().astype(str)), # 组内所有公司名列打平、去空、拼接;如果需要和原逻辑一致保留单字段去重,在dropna()后加.unique()即可 'Companies': ';'.join(group[company_columns].stack().dropna().astype(str)) }) ).reset_index(drop=True) print(df_new) print(time.strftime("%H:%M:%S", time.localtime()) + " end")
效果对照
示例输入
| Name | People1.Email | People1.CompanyName | People2.Email | People2.CompanyName | People3.Email | People3.CompanyName |
|---|---|---|---|---|---|---|
| Person A | email@somewhere.com | CompanyName | email@somewhere.com | CompanyName | 空 | 空 |
| Person A | email@somewhere.com | CompanyName | email@somewhere.com | CompanyName | 空 | 空 |
| Person B | 空 | 空 | email@somewhere.com | CompanyName | email@somewhere.com | CompanyName |
示例输出
| Name | Emails | Companies |
|---|---|---|
| Person A | email@somewhere.com;email@somewhere.com;email@somewhere.com;email@somewhere.com | CompanyName;CompanyName;CompanyName;CompanyName |
| Person B | email@somewhere.com;email@somewhere.com | CompanyName;CompanyName |
内容的提问来源于stack exchange,提问作者Maxcot
相关产品推荐
相关产品推荐

