2016-07-27 96 views
1

至少兩個詞我使用Pandas快,矢量str.contains的方法來檢查我的數據幀每一行是否包含從我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字符串匹配算法快得多。

回答

2

您可以使用concatlist 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 
+0

讓我們[繼續聊天討論](http://chat.stackoverflow.com/rooms/118456/discussion-between-jon-克萊門茨和-jezrael)。 –

2

假設ber應該是bar,您可以使用.apply帶套 - 注意,這確實整個單詞 - 不是子(如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) 

爲您提供:

0 False 
1 False 
2 False 
3  True 
4  True 
5 False 
6 False 
7 False 
Name: A, dtype: bool 
+0

謝謝,但我認爲應用將效率較低,str.contains導致其純粹的Python循環,讓我做一些測試 –

+1

@Noobie隨時讓我們知道你發現了什麼 - 我會好奇,看看不同之處: ) –

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)) 

我會檢查被別人:)提出的技術

+0

感謝pawelty無論如何嘗試:) –

相關問題