2017-02-03 67 views
0

我有一套我關心計數的標記。比方說,他們是:用Python計數並從結果中創建矩陣

pos_tags = ["NN", "NNS", "JJ"] 

我希望我的程序通過句子的清單,也許看起來像這樣重複:

sents = ["I want to go home.", "I have five dollars.", "The grass is green and wet."] 

我用nltk.pos_tag標記每個字與結果是:

['I', 'want', 'to', 'go', 'home', '.'] 
[('I', 'PRP'), ('want', 'VBP'), ('to', 'TO'), ('go', 'VB'), ('home', 'NN'), ('.', '.')] 
['I', 'have', 'five', 'dollars', '.'] 
[('I', 'PRP'), ('have', 'VBP'), ('five', 'CD'), ('dollars', 'NNS'), ('.', '.')] 
['The', 'grass', 'is', 'green', 'and', 'wet', '.'] 
[('The', 'DT'), ('grass', 'NN'), ('is', 'VBZ'), ('green', 'JJ'), ('and', 'CC'), ('wet', 'NN'), ('.', '.')] 

我要檢查是否有在這裏有pos_tags任何話,我想我有似乎做到了這一點;然而,我有很大的麻煩,以我想要的形式返回結果,這是一種矩陣樣式。

行將是句子的數量。在這種情況下,3.列將是標籤的數量。在這種情況下,還3.

最後的結果會是什麼樣子:

[1, 0, 0 
0, 1, 0 
2, 0, 1] 

這是我到目前爲止有:

def tagging(sents): 

    matrix = [] 
    pos_tags = ["NN", "NNS", "JJ"] 

    for sent in sents: 

     tokens = nltk.word_tokenize(sent) 

     tagged_tokens = nltk.pos_tag(tokens) 
     tagged_tokens_final = tagged_tokens 


    for key, val in tagged_tokens_final: 
     if val in common_pos_tags: 
      counting = val.count(val) 

回答

1

有一對夫婦的接近這個不同的方式問題。最簡單的可能是注意到每個句子都是獨立處理的。因此,你可以把所有的操作爲一個句子到一個單一的功能,然後運行它爲每個句子獨立:

tags = ['NN', 'NNS', 'JJ'] 

matrix = [None] * len(sents) 
for index, sent in enumerate(sents): 
    matrix[index] = do_counting(sent, tags) 

如果您願意擴大矩陣動態地而不是與[None] * len(sents)預先分配的,你也可以這樣做:

matrix = [] 
for sent in sents: 
    matrix.append(do_counting(sent, tags)) 

在這兩種情況下,do_counting是一個函數,需要一個句子串和標籤列表,返回矩陣的單排。如果您決定更改您感興趣的標籤的順序或名稱,標籤就是一個輸入。輸出將始終與輸入列表匹配。

解析將以nltk完成,就像您已經想到的那樣。計數最容易用collections.Counter對象來完成,這非常適合於此目的。它會統計每個標籤的出現次數。然後,我們可以選擇我們想要根據您在傳遞的第二個參數列表上的標籤:

from collections import Counter 
def do_counting(sentence, tags) 
    tokens = nltk.word_tokenize(sent) 
    tagged_tokens = nltk.pos_tag(tokens) 
    counts = Counter(tag for _, tag in tagged_tokens) 
    tag_counts = [counts[tag] for tag in tags] 
    return tag_counts 

請注意,我忽略計數的目的令牌。 _是Python中的有效變量名稱,但通常用於指示丟棄的參數。計數器可能被寫成

counts = Counter(item[0] for item in tagged_tokens) 

它不會是太困難的事計數自己,而不是使用Counter

def do_counting(sentence, tags) 
    tokens = nltk.word_tokenize(sent) 
    tagged_tokens = nltk.pos_tag(tokens) 
    counts = [sum(items[1] == tag for items in tagged_tokens) for tag in tags] 
    return counts 

希望我已經奠定了可以遵循的做法,但更多重要的是理解。我試圖給你提供一些選項,讓你可以在自己學習更多的時候感受一下可能性。

+0

非常感謝您的詳細解釋 - 計數部分特別有用!對於矩陣部分,我最終在numpy庫中使用了np.array - 像魅力一樣工作! – natalien

+0

沒問題。你可以從最終結果中創建一個numpy數組,或者從一開始就用一個來填充。我想堅持核心Python的這個答案,因爲它看起來像你想要更基本的東西。 –

2

有Python中的各種矩陣類型,利布斯,但我只是做了一個列表的列表

s1 = ['I', 'want', 'to', 'go', 'home', '.'] 
ts1 = [('I', 'PRP'), ('want', 'VBP'), ('to', 'TO'), ('go', 'VB'), ('home', 'NN'), ('.', '.')] 
s2 = ['I', 'have', 'five', 'dollars', '.'] 
ts2 = [('I', 'PRP'), ('have', 'VBP'), ('five', 'CD'), ('dollars', 'NNS'), ('.', '.')] 
s3 = ['The', 'grass', 'is', 'green', 'and', 'wet', '.'] 
ts3 = [('The', 'DT'), ('grass', 'NN'), ('is', 'VBZ'), ('green', 'JJ'), ('and', 'CC'), ('wet', 'NN'), ('.', '.')] 

pos_tags = ["NN", "NNS", "JJ"] 

嵌套列表理解並罰款這裏建造列表
sum(sen,())名單變平元組的列表 - 但不是最推薦的性能

tagd_sents = [ts1, ts2, ts3] 

tagm = [[sum(sen,()).count(tag) for tag in pos_tags] for sen in tagd_sents] 

print(*tagm, sep='\n') 
[1, 0, 0] 
[0, 1, 0] 
[2, 0, 1] 

瘋狂的物理學家是關於快速和骯髒的上面也都在一句話計數標籤正確,尊重數據structu re會更安全

+0

這絕對是一個聰明的方法。特別是'sum(sen,())'是我的一天。話雖如此,如果其中一個標籤原樣出現在句子中,這將會失敗。 'sum(x [1] for x in sen,())'可能是一個更好的選擇。一個三重嵌套的理解,仍然很清晰:) –