是否可以使用带有 pandas 的正则表达式在两个数据帧之间执行左联接/合并?



我正在尝试使用Python中的正则表达式执行左合并,该表达式可以处理多对多关系。 例:

df1 = pd.DataFrame(['a','b','c','d'], columns = ['col1'])
df1['regex'] = '.*' + df1['col1'] + '.*'
col1    regex
0 a   .*a.*
1 b   .*b.*
2 c   .*c.*
3 d   .*d.*
df2 = pd.DataFrame(['ab','a','cd'], columns = ['col2'])
col2
0 ab
1 a
2 cd
# Merge on regex column to col2
out = pd.DataFrame([['a','ab'],['a','a'],['b','ab'],['c','cd'], 
['d','cd']],columns = ['col1','col2'])

col1    col2
0 a   ab
1 a   a
2 b   ab
3 c   cd
4 d   cd

您可以使用创建自定义函数来查找两个数据框的所有匹配索引,然后提取这些索引并使用pd.concat

import re
def merge_regex(df1, df2):
idx = [(i,j) for i,r in enumerate(df1.regex) for j,v in enumerate(df2.col2) if re.match(r,v)]
df1_idx, df2_idx = zip(*idx)
t = df1.iloc[list(df1_idx),0].reset_index(drop=True)
t1 = df2.iloc[list(df2_idx),0].reset_index(drop=True)
return pd.concat([t,t1],axis=1)
merge_regex(df1, df2)
col1 col2
0    a   ab
1    a    a
2    b   ab
3    c   cd
4    d   cd
<小时 />

时间结果

# My solution
In [292]: %timeit merge_regex(df1,df2)
1.21 ms ± 22.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
#Chris's solution
In [293]: %%timeit
...: df1['matches'] = df1.apply(lambda r: [x for x in df2['col2'].values if re.findall(r['regex'], x)], axis=1)
...: 
...: df1.set_index('col1').explode('matches').reset_index().drop(columns=['regex'])
...:
...:
4.62 ms ± 25.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

我会查看每个 col1 值,并在 df2 的 col2 中找到模式匹配的所有值,并列出并将其放入名为"matches"的列中。完成后,您可以将 col1 设置为索引,分解匹配列以使它们成为每行一个,然后摆脱正则表达式模式列。

import re
import pandas as pd
df1 = pd.DataFrame(['a','b','c','d'], columns = ['col1'])
df1['regex'] = '.*' + df1['col1'] + '.*'
df2 = pd.DataFrame(['ab','a','cd'], columns = ['col2'])

df1['matches'] = df1.apply(lambda r: [x for x in df2['col2'].values if re.findall(r['regex'], x)], axis=1)
df1.set_index('col1').explode('matches').reset_index().drop(columns=['regex'])

col1    matches
0   a       ab
1   a       a
2   b       ab
3   c       cd
4   d       cd

最新更新