Pandas:加入部分字符串匹配,如Excel VLOOKUP

Hoe*_*nie 6 python join dataframe python-3.x pandas

我试图在Python中执行一个与Excel中的VLOOKUP非常相似的操作.StackOverflow上有很多与此相关的问题,但它们与这个用例略有不同.希望任何人都可以指导我朝着正确的方向前进.我有以下两个pandas数据帧:

df1 = pd.DataFrame({'Invoice': ['20561', '20562', '20563', '20564'],
                    'Currency': ['EUR', 'EUR', 'EUR', 'USD']})
df2 = pd.DataFrame({'Ref': ['20561', 'INV20562', 'INV20563BG', '20564'],
                    'Type': ['01', '03', '04', '02'],
                    'Amount': ['150', '175', '160', '180'],
                    'Comment': ['bla', 'bla', 'bla', 'bla']})

print(df1)
    Invoice Currency
0   20561   EUR
1   20562   EUR
2   20563   EUR
3   20564   USD

print(df2)
    Ref         Type    Amount  Comment
0   20561       01      150     bla
1   INV20562    03      175     bla
2   INV20563BG  04      160     bla
3   20564       02      180     bla
Run Code Online (Sandbox Code Playgroud)

现在我想创建一个新的数据帧(df3),我根据发票号码将两者结合起来.问题是发票号码并不总是"完全匹配",但有时在df2 ['Ref']中是"部分匹配".因此,加入"发票"并未提供所需的输出,因为它不会复制发票20562和20563的数据,请参阅下文:

df3 = df1.join(df2.set_index('Ref'), on='Invoice')

print(df3)
    Invoice Currency    Type    Amount  Comment
0   20561   EUR         01       150    bla
1   20562   EUR         NaN      NaN    NaN
2   20563   EUR         NaN      NaN    NaN
3   20564   USD         02       180    bla
Run Code Online (Sandbox Code Playgroud)

有没有办法加入部分匹配?我知道如何用正则表达式"清理"df2 ['Ref'],但这不是我追求的解决方案.有了for循环,我得到了很长的路,但这不是很Pythonic.

df4 = df1.copy()
for i, row in df1.iterrows():
    tmp = df2[df2['Ref'].str.contains(row['Invoice'])]
    df4.loc[i, 'Amount'] = tmp['Amount'].values[0]

print(df4)
Invoice     Currency    Amount
0   20561   EUR         150
1   20562   EUR         175
2   20563   EUR         160
3   20564   USD         180
Run Code Online (Sandbox Code Playgroud)

str.contains()能不能以更优雅的方式使用?非常感谢您的帮助!

jpp*_*jpp 2

这是使用 的一种方法pd.Series.apply,它只是一个薄薄的循环。您正在寻找“部分字符串合并”,我不确定它是否以矢量化形式存在。

df4 = df1.copy()

def get_amount(x):
    return df2.loc[df2['Ref'].str.contains(x), 'Amount'].iloc[0]

df4['Amount'] = df4['Invoice'].apply(get_amount)

print(df4)

  Currency Invoice Amount
0      EUR   20561    150
1      EUR   20562    175
2      EUR   20563    160
3      USD   20564    180
Run Code Online (Sandbox Code Playgroud)