【问题标题】:Partial String Matching between Pandas DataFramesPandas DataFrame 之间的部分字符串匹配
【发布时间】:2019-08-08 21:12:08
【问题描述】:

我已经看到关于部分字符串匹配合并 herehere 和其他地方的讨论,但没有关于如何在包含超字符串而不是子字符串的表上执行此操作。

给定样本数据

df1 = pd.DataFrame({'uri': ['http://www.foo.com/index', 
                            'https://bar.net/directory', 
                            'www.baz.gov/aboutus']})
df2 = pd.DataFrame({'fqdn': ['www.foo.com',
                             'www.qux.mil']})
print(df1)

                         uri
0   http://www.foo.com/index
1  https://bar.net/directory
2        www.baz.gov/aboutus
print(df2)

          fqdn
0  www.foo.com
1  www.qux.mil

我的最终目标是从df1 中删除包含df2any 子字符串的行。在实际数据中,df1 有几百万行,df2 有几百行,df1 中的任何给定行在df2 中最多有一个子字符串。

鉴于示例数据,我希望最终得到一个类似的数据框

                         uri
0  https://bar.net/directory
1        www.baz.gov/aboutus

按照我的逻辑,中间步骤是生成

                         uri           fqdn
0   http://www.foo.com/index    www.foo.com
1  https://bar.net/directory         np.NaN
2        www.baz.gov/aboutus         np.NaN

但我不知道如何检查df2df1.apply() 中的所有值。


编辑:

虽然下面的两个答案都有效,但通过编译正则表达式对象并使用extract,我在特定场景中获得了最快的结果:

import re

fqdn_list= re.compile(f"({'|'.join(df2.fqdn)})")

df1['fqdn'] = df1.uri.str.extract(fqdn_list)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是你需要的吗? str.findall

    df1.uri.str.findall(df2.fqdn.str.cat(sep='|')).str[0]
    Out[192]: 
    0    www.foo.com
    1            NaN
    2            NaN
    Name: uri, dtype: object
    #df1['fqdn']=df1.uri.str.findall(df2.fqdn.str.cat(sep='|')).str[0]
    

    【讨论】:

    • +1 这在玩具示例上非常有效,但我不知道它是否可以缩放到我的集合的大小,或者我是否需要短路的东西。我正在超越自己。一旦我早上可以测试,我会接受。
    【解决方案2】:

    df2 中的字符串与管道 (|) 连接起来,作为分隔符,它是正则表达式中的 or 运算符。这样我们就可以检查df1 是否包含这些字符串,并使用str.contains~(即not 运算符)删除它们;

    m = ~df1['uri'].str.contains('|'.join(df2['fqdn']))
    df1[m]
    

    输出

                             uri
    1  https://bar.net/directory
    2        www.baz.gov/aboutus
    

    【讨论】:

    • 虽然在玩具套装上进行测试时,无需中间步骤即可完成我需要的工作,但即使应用于真实数据的子集,它也永远不会完成,而 WeNYoBen 的方法几乎可以立即运行。这很奇怪吗?
    • 是的,这很奇怪,而且是因为一个错字。
    • 在使用多达 1M 字符串的样本进行进一步测试后,您的解决方案大约快 20%。
    • 很高兴听到这个消息。很高兴我能帮上忙。 @安迪
    • 通过编译一个正则表达式对象,我设法获得了显着的速度提升 (~25%),如果您有兴趣,请查看我的问题底部。
    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 2012-06-15
    相关资源
    最近更新 更多