我在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字符串匹配算法快得多。
答案 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))
我会检查其他人提出的技巧:)