2017-05-12 6 views
0

を使用して文のリストのリストを越えIは、それぞれ内部リストは、単語にトークン化された文であるリストのリストを持っています:計算nGramsはNLTK

numSentences = len(sentences) 
nGrams = [] 
for i in range(0, numSentences): 
     nGrams.append(list(ngrams(sentences, 2))) 

これは、リスト全体ではなく、各内部リストは個々の単語(それは幾分予測可能である文の数について繰り返される)のバイグラムを見つけることになる:

[[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']), 
    (['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])], 
[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']), 
(['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])], 
[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']), 
(['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])]] 

各文のnグラムを(単語単位で)どのように計算するのですか?言い換えれば、nGramsが複数のリスト項目にまたがらないようにする方法は?ここに私の所望の出力は次のようになります。

farmer plants 
plants grain 
fisher catches 
catches tuna 
police officer 
officer fights 
fights crime 

答えて

0

使用list comprehensionchain to flatten the list

>>> from itertools import chain 
>>> from collections import Counter 
>>> from nltk import ngrams 

>>> x = [['farmer', 'plants', 'grain'], ['fisher', 'catches', 'tuna'], ['police', 'officer', 'fights', 'crime']] 

>>> Counter(chain(*[ngrams(sent,2) for sent in x])) 
Counter({('plants', 'grain'): 1, ('police', 'officer'): 1, ('farmer', 'plants'): 1, ('officer', 'fights'): 1, ('fisher', 'catches'): 1, ('fights', 'crime'): 1, ('catches', 'tuna'): 1}) 

>>> c = Counter(chain(*[ngrams(sent,2) for sent in x])) 

keys of the Counter dictionaryを取得:

>>> c.keys() 
[('plants', 'grain'), ('police', 'officer'), ('farmer', 'plants'), ('officer', 'fights'), ('fisher', 'catches'), ('fights', 'crime'), ('catches', 'tuna')] 

Join strings with spaces

>>> [' '.join(b) for b in c.keys()] 
['plants grain', 'police officer', 'farmer plants', 'officer fights', 'fisher catches', 'fights crime', 'catches tuna'] 
0

各文のnグラムをとり、結果をまとめます。あなたはおそらくそれらを数えたいと思うでしょう。巨大なコレクションに入れないでください。単語のリストのリストとしてsentencesで始まる:

counts = collections.Counter() # or nltk.FreqDist() 
for sent in sentences: 
    counts.update(nltk.ngrams(sent, 2)) 

それとも、一つの文字列ではなく、タプルあなたの鍵を好む場合:

for sent in sentences: 
    count.update(" ".join(n) for n in nltk.ngrams(sent, 2)) 

ことにあり、本当にすべてです。次に、最も一般的なものなどを見ることができます。

print(counts.most_common(10)) 

PS。あなたが本当にバイグラムを積み重ねたいのであれば、このようにするでしょう。 (あなたのコードは、文章の「バイグラム」を、単語ではなく、sentences[i]と書いていないので、形成します)。しかし、このステップをスキップして直接数えてください。

all_ngrams = [] 
for sent in sentences: 
    all_ngrams.extend(nltk.ngrams(sent, 2)) 
0

またscikit学習のCountVectorizer代替としての使用を検討することができます。

from sklearn.feature_extraction.text import CountVectorizer 

sents = list(map(lambda x: ' '.join(x), sentences)) # input is a list of sentences so I map join first 
count_vect = CountVectorizer(ngram_range=(2,2)) # bigram 
count_vect.fit(sents) 
count_vect.vocabulary_ 

これはあなたを与えるだろう。

{'catches tuna': 0, 
'farmer plants': 1, 
'fights crime': 2, 
'fisher catches': 3, 
'officer fights': 4, 
'plants grain': 5, 
'police officer': 6}