【问题标题】:Match Unknown Number of String Elements in Pandas Column匹配 Pandas 列中未知数量的字符串元素
【发布时间】:2016-04-15 20:50:21
【问题描述】:

我有一个字符串列表,需要对数据框中的某个列进行搜索:

search_strings = ['foo bar', 'bar such foo', 'very wow foo']

我正在尝试检索数据框中与列表中每个字符串中任何顺序的单词匹配的行。数据框可能如下所示:

ID string_col
1  foo bar
2  bar foo
3  foo very bar
4  bar such foo
5  foo wow very

我很高兴发现我可以使用“|”带有 str.contains 的运算符(检索所有 5 行):

df[df['string_col'].str.contains('foo|bar')]

我以为我可以遍历我的列表,用“&”拆分并加入它们以执行类似的操作(我错误地认为这会检索 4 行):

df[df['string_col'].str.contains('foo&bar')]

然而,事实证明这不是你能做到的。知道如何根据字符串列表轻松检索匹配的列,每个字符串都有未知数量的单词吗?

谢谢!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以对拆分字符串使用列表推导,确保所有目标词都存在:

    words = ['foo', 'bar']
    df['word_match'] = [all(word in values for word in words) 
                        for values in df.string_col.str.split(" ")]
    
    >>> df
       ID    string_col word_match
    0   1       foo bar       True
    1   2       bar foo       True
    2   3  foo very bar       True
    3   4  bar such foo       True
    4   5       foo wow      False
    

    时间

    %timeit df['word_match'] = [all(word in values for word in words) for values in df.string_col.str.split(" ")]
    1000 loops, best of 3: 320 µs per loop
    
    %timeit df['word_match'] = df[df['string_col'].str.contains('foo') & df['string_col'].str.contains('bar')]
    1000 loops, best of 3: 1.23 ms per loop
    

    在较大的数据集上,第二种方法略胜一筹:

    df2 = pd.concat([df]*10000, ignore_index=True)
    
    %timeit df2['word_match'] = [all(word in values for word in words) for values in df2.string_col.str.split(" ")]
    10 loops, best of 3: 70.9 ms per loop
    
    %timeit df2['word_match'] = df2[df2['string_col'].str.contains('foo') & df2['string_col'].str.contains('bar')]
    10 loops, best of 3: 63.7 ms per loop
    

    【讨论】:

    • 您可能希望使用all(word in set(values) for...查看您的数据是否有任何性能提升
    【解决方案2】:

    您必须使用 str.contains 传递 2 个条件并将它们括在括号中并使用 &

    In [11]:
    df[df['string_col'].str.contains('foo') & df['string_col'].str.contains('bar')]
    
    Out[11]:
       ID    string_col
    0   1       foo bar
    1   2       bar foo
    2   3  foo very bar
    3   4  bar such foo
    

    【讨论】:

    • 谢谢!我更具体地编辑了我的帖子 - 我有一种情况,我不知道我需要匹配多少个单词。
    • 你刚刚定义了多个掩码和&他们所有
    • 例如foo_mask = df['string_col'].str.contains('foo') bar_mask=df['string_col'].str.contains('bar') filtered = df[foo & bar]你可以连续构建这样的面具,然后随意组合它们
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2019-02-16
    • 1970-01-01
    • 2016-06-09
    • 2020-09-09
    相关资源
    最近更新 更多