Pandas:检查字符串是否包含列表中至少两个单词

时间:2016-07-27 12:30:34

标签: python pandas

我在str.contains中使用快速的矢量化Pandas方法来检查数据框中的每一行是否包含来自list_word至少一个单词

list_words='foo ber haa'

df = pd.DataFrame({'A' : ['foo foor', 'bar bar', 'foo hoo', 'bar haa',
                         'foo bar', 'bar bur', 'foo fer', 'foo for']})  
df
Out[113]: 
          A
0  foo foor
1   bar bar
2   foo hoo
3   bar haa
4   foo bar
5   bar bur
6   foo fer
7   foo for

df.A.str.contains("|".join(list_words.split(" ")))
Out[114]: 
0     True
1    False
2     True
3     True
4     True
5    False
6     True
7     True
Name: A, dtype: bool

问题是:如何检查每行中是否至少包含列表中的两个单词?

我想坚持str.contains,因为它比其他python字符串匹配算法快得多。

3 个答案:

答案 0 :(得分:3)

您可以concat使用list comprehension

#changed ber to bar
list_words='foo bar haa'

df = pd.DataFrame({'A' : ['foo foor', 'bar bar', 'foo hoo', 'bar haa',
                         'foo bar', 'bar bur', 'foo fer', 'foo for']})  

print (df)
          A
0  foo foor
1   bar bar
2   foo hoo
3   bar haa
4   foo bar
5   bar bur
6   foo fer
7   foo for

print((pd.concat([df.A.str.contains(word,regex=False) for word in list_words.split()],axis=1))
          .sum(1) > 1)

0    False
1    False
2    False
3     True
4     True
5    False
6    False
7    False
dtype: bool

<强>计时

def jon(df):
    set_words = set(list_words.split())
    return df.A.apply(lambda L: len(set(L.split()) & set_words) > 1)
In [292]: %timeit ((pd.concat([df.A.str.contains(word) for word in list_words.split()], axis=1)).sum(1) > 1)
100 loops, best of 3: 16 ms per loop

In [325]: %timeit (jon(df))
100 loops, best of 3: 8.97 ms per loop

In [294]: %timeit ((pd.concat([df.A.str.contains(word,regex=False) for word in list_words.split()], axis=1)).sum(1) > 1)
100 loops, best of 3: 8.13 ms per loop

In [295]: %timeit df['A'].map(lambda x: check(x, list_words))
100 loops, best of 3: 14.7 ms per loop

答案 1 :(得分:2)

假设ber应为bar,您可以将.apply用于集合 - 请注意,整个单词 - 不是子字符串(例如{{1}在foo)中找不到......

foor

给你:

import pandas as pd

list_words='foo bar haa'
set_words = set(list_words.split())

df = pd.DataFrame({'A' : ['foo foor', 'bar bar', 'foo hoo', 'bar haa',
                         'foo bar', 'bar bur', 'foo fer', 'foo for']})

df.A.apply(lambda L: len(set(L.split()) & set_words) > 1)

答案 2 :(得分:1)

我是一个有熊猫的初学者(和一般的python)所以想要尝试它作为挑战而不是获得upvotes :)。刚刚使用了我所知道的技术,但它们明显慢于其他人提出的技术。

def check(row, string):
    #tokenize string
    string_list = string.split() 
    #tokenize row
    row_list = row.split()

    counter = 0
    used_words = []
    for word in row_list:
        used_words.append(word)
        if word in string_list and not(used_words.count(word) >1):
            counter += 1
    if counter >= 2:
        return True
    else:
        return False

df['check'] = df['A'].map(lambda x: check(x, list_words))

我会检查其他人提出的技巧:)