2016-12-16 96 views
1

我正在嘗試創建單詞組。首先,我計算所有單詞。然後我通過字數建立前10個單詞。然後,我想根據前10名創建10組單詞。每個組由所有位於頂部單詞之前和之後的單詞組成。基於前後單詞的python單詞分組

我有存儲在一個Python大熊貓數據幀的調查結果結構化這樣

Question_ID | Customer_ID | Answer 
    1   234   Data is very important to use because ... 
    2   234   We value data since we need it ... 

我也節約了答案列作爲一個字符串。

我使用下面的代碼,以查找前一個單詞後3個字(其實我不得不創建一個字符串出答案柱)

answers_str = df.Answer.apply(str) 
for value in answers_str: 
    non_data = re.split('data|Data', value) 
    terms_list = [term for term in non_data if len(term) > 0] # skip empty terms 
    substrs = [term.split()[0:3] for term in terms_list] # slice and grab first three terms 
    result = [' '.join(term) for term in substrs] # combine the terms back into substrings 
    print result 

我一直在手動創建組詞 - 但有沒有辦法在Python中做到這一點?

因此,基於與字數組上面的例子是這樣的:

group "data": 
       data : 2 
       important: 1 
       value: 1 
       need:1 

那麼當它在整個文件中,將有另一組:

group "analytics: 
       analyze: 5 
       report: 7 
       list: 10 
       visualize: 16 

這個想法是擺脫「我們」,「到」,「是」 - 但我可以手動做到這一點,如果這是不可能的。

然後建立10個最常用的單詞(按單詞計數),然後創建10個單詞,前後有10個單詞。

回答

2

我們可以使用這個正則表達式。我們將使用正則表達式

((?:\b\w+?\b\s*){0,3})[dD]ata((?:\s*\b\w+?\b){0,3}) 

你可以測試自己here,前後數據的每種情況後提取三個字

首先,讓我們刪除所有的話我們不比如來自絃樂。

import re 

# If you're processing a lot of sentences, it's probably wise to preprocess 
#the pattern, assuming that bad_words is the same for all sentences 
def remove_words(sentence, bad_words): 
    pat = r'(?:{})'.format(r'|'.join(bad_words)) 
    return re.sub(pat, '', sentence, flags=re.IGNORECASE) 

的,我們想在每行

data_pat = r'((?:\b\w+?\b\s*){0,3})[dD]ata((?:\s*\b\w+?\b){0,3})' 
res = re.findall(pat, s, flags=re.IGNORECASE) 

給我們的字符串元組的列表,圍繞數據的話。我們希望在分割後得到這些字符串的列表。

from itertools import chain 
list_of_words = list(chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res)))))) 

這並不美觀,但它的工作原理。基本上,我們將元組從列表中拉出,從每個元組中拉出字符串,然後分割每個字符串,然後將所有字符串從列表中拖出來,放入一個大列表中。

讓我們把這一切與你的pandas代碼一起。 pandas不是我最強的地方,所以如果你看到一些奇怪的東西,請不要以爲我沒有犯過一些基本的錯誤。

import re 
from itertools import chain 
from collections import Counter  

def remove_words(sentence, bad_words): 
    pat = r'(?:{})'.format(r'|'.join(bad_words)) 
    return re.sub(pat, '', sentence, flags=re.IGNORECASE) 

bad_words = ['we', 'is', 'to'] 
sentence_list = df.Answer.apply(lambda x: remove_words(str(x), bad_words)) 
c = Counter() 
data_pat = r'((?:\b\w+?\b\s*){0,3})data((?:\s*\b\w+?\b){0,3})' 
for sentence in sentence_list: 
    res = re.findall(data_pat, sentence, flags=re.IGNORECASE) 
    words = chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res))))) 
    c.update(words) 

我們正在使用的正則表達式的好處是所有複雜的部分都不關心我們使用的是什麼單詞。有輕微的變化,我們可以做一個格式字符串

base_pat = r'((?:\b\w+?\b\s*){{0,3}}){}((?:\s*\b\w+?\b){{0,3}})' 

這樣

base_pat.format('data') == data_pat 

所以用文字的一些列表中,我們要收集有關key_words

import re 
from itertools import chain 
from collections import Counter  

def remove_words(sentence, bad_words): 
    pat = r'(?:{})'.format(r'|'.join(bad_words)) 
    return re.sub(pat, '', sentence, flags=re.IGNORECASE) 


bad_words = ['we', 'is', 'to'] 

sentence_list = df.Answer.apply(lambda x: remove_words(str(x), bad_words)) 

key_words = ['data', 'analytics'] 
d = {} 

base_pat = r'((?:\b\w+?\b\s*){{0,3}}){}((?:\s*\b\w+?\b){{0,3}})' 
for keyword in key_words: 
    key_pat = base_pat.format(keyword) 
    c = Counter() 
    for sentence in sentence_list: 
     res = re.findall(key_pat, sentence, flags=re.IGNORECASE) 
     words = chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res))))) 
     c.update(words) 
    d[keyword] = c 

現在我們有一個字典d映射關鍵字,如dataanalyticsCounter s映射單詞不在我們的關聯關鍵字附近的黑名單上。像

d= {'data'  : Counter({ 'important' : 2, 
          'very'  : 3}), 
    'analytics' : Counter({ 'boring' : 5, 
          'sleep'  : 3}) 
    } 

至於如何獲得前10個字的東西,這是基本的東西Counter是最好的。

key_words, _ = zip(*Counter(w for sentence in sentence_list for w in sentence.split()).most_common(10)) 
+0

非常感謝你;使用我創建的字符串而不是熊貓數據框會更容易嗎? answers_str = df.Answer.apply(str) – jeangelj

+0

我收到一條錯誤消息SyntaxError:無效的語法和一個箭頭指向s中的「words」 – jeangelj

+0

@jeangelj我搞亂了我的複製粘貼,所以有一個缺失的括號。我編輯它,所以它現在應該工作 –