如何快速合并Pandas DataFrame?多列合并效率优化问询
高效合并Pandas DataFrame同组列的优化方案
场景一:按固定前缀分组合并列
原始数据与需求
原始DataFrame列名以前缀_数字格式命名,需要将前缀相同的列合并,去除None值,保留每行第一个非空值:
import pandas as pd df = pd.DataFrame( {'number_1': ['1', '2', None, None, '5', '6', '7', '8'], 'fruit_1': ['apple', 'banana', None, None, 'watermelon', 'peach', 'orange', 'lemon'], 'name_1': ['tom', 'jerry', None, None, 'paul', 'edward', 'reggie', 'nicholas'], 'number_2': [None, None, '3', None, None, None, None, None], 'fruit_2': [None, None, 'blueberry', None, None, None, None, None], 'name_2': [None, None, 'anthony', None, None, None, None, None], 'number_3': [None, None, '3', '4', None, None, None, None], 'fruit_3': [None, None, 'blueberry', 'strawberry', None, None, None, None], 'name_3': [None, None, 'anthony', 'terry', None, None, None, None], } )
目标结果:
number fruit name 0 1 apple tom 1 2 banana jerry 2 3 blueberry anthony 3 4 strawberry terry 4 5 watermelon paul 5 6 peach edward 6 7 orange reggie 7 8 lemon nicholas
优化方案
原嵌套循环+多次concat/assign的方式效率极低,改用Pandas内置的groupby操作,利用向量运算大幅提升速度:
# 按列名前缀分组,取每行第一个非空值 grouped = df.groupby(lambda col: col.split('_')[0], axis=1) result = grouped.first() print(result)
原理:groupby通过lambda函数提取列名前缀作为分组键,first()方法会自动遍历每行,保留该组内第一个非空值,完全匹配需求且避免了冗余的循环操作。
场景二:按正则处理后的列名分组合并
原始数据与需求
列名包含_C+1-3位数字的冗余部分,需要去除该部分后,将剩余名称相同的列合并:
import pandas as pd df = pd.DataFrame( {'number_C1_E1': ['1', '2', None, None, '5', '6', '7', '8'], 'fruit_C11_E1': ['apple', 'banana', None, None, 'watermelon', 'peach', 'orange', 'lemon'], 'name_C111_E1': ['tom', 'jerry', None, None, 'paul', 'edward', 'reggie', 'nicholas'], 'number_C2_E2': [None, None, '3', None, None, None, None, None], 'fruit_C22_E2': [None, None, 'blueberry', None, None, None, None, None], 'name_C222_E2': [None, None, 'anthony', None, None, None, None, None], 'number_C3_E1': [None, None, '3', '4', None, None, None, None], 'fruit_C33_E1': [None, None, 'blueberry', 'strawberry', None, None, None, None], 'name_C333_E1': [None, None, 'anthony', 'terry', None, None, None, None], } )
目标结果:
number_E1 fruit_E1 name_E1 number_E2 fruit_E2 name_E2 0 1 apple tom None None None 1 2 banana jerry None None None 2 3 blueberry anthony 3 blueberry anthony 3 4 strawberry terry None None None 4 5 watermelon paul None None None 5 6 peach edward None None None 6 7 orange reggie None None None 7 8 lemon nicholas None None None
优化方案
用正则表达式去除列名中的冗余部分,再通过groupby完成合并:
import re # 定义正则:匹配_C后接1-3位数字的部分 pattern = re.compile(r'_C\d{1,3}') # 按处理后的列名分组,取每行第一个非空值 grouped = df.groupby(lambda col: pattern.sub('', col), axis=1) result = grouped.first() # 可选:按列名排序,保证结果顺序符合预期 result = result.sort_index(axis=1) print(result)
原理:正则替换快速统一分组键,后续groupby.first()的向量操作避免了循环,处理大量列时性能优势明显。
原代码低效原因
原方案采用嵌套循环遍历列,每次concat和assign都会生成新的DataFrame,导致频繁的内存拷贝和冗余计算;而groupby是Pandas内部优化的向量化操作,直接对整组列进行处理,大幅减少了内存开销和计算时间。
内容的提问来源于stack exchange,提问作者haojie
相关产品推荐
相关产品推荐

