如何在Pandas中结合正则表达式实现DataFrame的关联操作?
基于正则表达式关联两个Pandas DataFrame
我有两个pandas DataFrame:df1和df2。其中df1的"Box"列包含正则表达式,用来表示不同人员对应的箱子匹配规则:
df1
Person Box 0 Alex Box 1 1 Linda Box 3 2 David Box .* 3 Rachel Box [1-2]
df2
Box Item Qty. 0 Box 1 Apple 4 1 Box 1 Blueberry 12 2 Box 2 Lemon 1 3 Box 2 Papaya 2 4 Box 3 Apple 2
我需要基于"Box"列关联这两个DataFrame,同时正确解析正则表达式(Pandas原生的join/merge不支持正则匹配),最终得到如下结果:
目标结果
Person Box Item Qty. 0 Alex Box 1 Apple 4 1 Alex Box 1 Blueberry 12 2 Linda Box 3 Apple 2 3 David Box 1 Apple 4 4 David Box 1 Blueberry 12 5 David Box 2 Lemon 1 6 David Box 2 Papaya 2 7 David Box 3 Apple 2 8 Rachel Box 1 Apple 4 9 Rachel Box 1 Blueberry 12 10 Rachel Box 2 Lemon 1 11 Rachel Box 2 Papaya 2
我尝试用列表推导实现,结果的行是对的,但丢失了左DataFrame的Person列:
def joinWithRegEx(left: pd.DataFrame, right: pd.DataFrame, left_on: str, right_on: str): df = pd.DataFrame df = pd.concat([right[right[right_on].str.match(entry)] for entry in left[left_on]], ignore_index=True) ''' Left-Join of two DataFrame with considered Rege ''' return df
我以为这是比较常见的场景,难道Pandas不适合做这类任务?
解决方案
方法1:笛卡尔积+正则过滤
先构造两个DataFrame的笛卡尔积,再筛选出符合正则匹配的行,能完整保留左表的所有列:
import pandas as pd # 添加临时key实现交叉连接 df1['key'] = 0 df2['key'] = 0 cross_df = pd.merge(df1, df2, on='key').drop('key', axis=1) # 筛选df2.Box匹配df1.Box正则的行 result = cross_df[cross_df.apply(lambda row: row['Box_y'].match(row['Box_x']), axis=1)] # 调整列名和顺序 result = result.rename(columns={'Box_x': '规则Box', 'Box_y': 'Box'}) result = result[['Person', 'Box', 'Item', 'Qty.']].reset_index(drop=True) print(result)
方法2:逐行匹配合并
遍历左表每一行,找到右表中匹配正则的行,再合并左表当前行的人员信息,最后拼接所有结果:
def joinWithRegEx(left: pd.DataFrame, right: pd.DataFrame, left_on: str, right_on: str): frames = [] for _, row in left.iterrows(): # 筛选右表中匹配当前正则的行 matched_rows = right[right[right_on].str.match(row[left_on])] # 合并当前人员信息 matched_rows = matched_rows.assign(Person=row['Person']) frames.append(matched_rows) # 拼接并调整列顺序 return pd.concat(frames, ignore_index=True)[['Person', 'Box', 'Item', 'Qty.']] # 调用函数得到结果 final_result = joinWithRegEx(df1, df2, 'Box', 'Box') print(final_result)
这两种方法都能得到目标结果,且保留了Person列。Pandas完全可以处理这类正则匹配关联的场景,只是原生merge不支持直接正则匹配,需要手动实现匹配逻辑。
内容的提问来源于stack exchange,提问作者Elynvalur
相关产品推荐
相关产品推荐

