如何高效合并一列包含另一列子串的两个pandas DataFrame
两个DataFrame子串匹配合并的高效实现
你原来的嵌套循环时间复杂度为O(n*m)(n为df1行数,m为df2行数),数据量稍大就会非常慢,推荐用正则批量匹配的方案,时间复杂度接近O(n),是pandas原生的高效实现:
实现步骤
- 预处理df2的匹配串,避免正则特殊字符报错,同时按匹配串长度降序排序保证最长匹配优先
- 构造正则匹配模式,批量从df1的ProductReview列提取匹配到的ReviewMessage
- 基于提取到的匹配字段做表关联
代码示例
import pandas as pd import re # 示例数据(可替换为真实数据) df1 = pd.DataFrame({'ProductReview':['11/02/2020 c1r1 good product','27/08/2020 c2r1 product function1 could be better', '01/02/2020 c3r1 satisfactory product'], 'Feature1': ['feature21','feature22','feature23'], 'Feature2': ['feature11','feature12','feature13']}) df2 = pd.DataFrame({'Column1':['c1r1','c2r1'], 'ReviewMessage' : ['good product','product function1 could be better'],'New_value':['1','2']}) # 1. 预处理匹配串:转义正则特殊字符,按长度降序排序保证长串优先匹配 sorted_patterns = sorted(df2['ReviewMessage'].astype(str), key=len, reverse=True) escaped_patterns = [re.escape(p) for p in sorted_patterns] match_pattern = '|'.join(escaped_patterns) # 2. 批量提取匹配到的ReviewMessage df1['matched_review'] = df1['ProductReview'].str.extract(f'({match_pattern})', expand=False) # 3. 关联两个表 merged_df = df1.merge( df2, left_on='matched_review', right_on='ReviewMessage', how='left' ).drop(columns=['matched_review']) # 可删除临时匹配列
结果说明
对应示例数据,合并后的merged_df第三行因为没有匹配到df2的内容,ReviewMessage、Column1、New_value字段都会显示为NaN,符合需求。如果只需要保留匹配成功的行,把how='left'改成how='inner'即可。
特殊场景适配
- 如果存在单条ProductReview匹配多个ReviewMessage的情况,把
str.extract换成str.extractall,再做关联即可处理多匹配场景 - 匹配不需要考虑ProductReview里子串的位置,完全适配r1位置不固定的要求
- 数据量超过千万级时,可以把该逻辑迁移到PySpark上,语法几乎一致,性能更强
内容的提问来源于stack exchange,提问作者Suneha K S
相关产品推荐
相关产品推荐

