合并生成器对象以计算 NLTK 中的频率
Merge generator objects to calculate frequency in NLTK
我正在尝试使用 nltk
中的 ngram
和 freqDist
函数计算各种 ngrams
的频率。
由于 ngram
函数输出是一个 generator
对象,我想在计算频率之前合并每个 ngram 的输出。
但是,我 运行 遇到了合并各种生成器对象的问题。
我已经尝试 itertools.chain
,它创建了一个 itertools
对象,而不是合并生成器。
我终于选择了 permutations
,但之后解析对象似乎是多余的。
到目前为止的工作代码是:
import nltk
from nltk import word_tokenize, pos_tag
from nltk.collocations import *
from itertools import *
from nltk.util import ngrams
import re
corpus = 'testing sentences to see if if if this works'
token = word_tokenize(corpus)
unigrams = ngrams(token,1)
bigrams = ngrams(token,2)
trigrams = ngrams(token,3)
perms = list(permutations([unigrams,bigrams,trigrams]))
fdist = nltk.FreqDist(perms)
for x,y in fdist.items():
for k in x:
for v in k:
words = '_'.join(v)
print words, y
正如您在结果中看到的那样,freq dist 没有正确计算来自各个生成器对象的单词,因为每个生成器对象的频率都是 1。
有没有更 pythonic 的方法来正确地做到这一点?
使用everygrams
,它returns给定范围n的所有n-gram。
>>> from nltk import everygrams
>>> from nltk import FreqDist
>>> corpus = 'testing sentences to see if if if this works'
>>> everygrams(corpus.split(), 1, 3)
<generator object everygrams at 0x7f4e272e9730>
>>> list(everygrams(corpus.split(), 1, 3))
[('testing',), ('sentences',), ('to',), ('see',), ('if',), ('if',), ('if',), ('this',), ('works',), ('testing', 'sentences'), ('sentences', 'to'), ('to', 'see'), ('see', 'if'), ('if', 'if'), ('if', 'if'), ('if', 'this'), ('this', 'works'), ('testing', 'sentences', 'to'), ('sentences', 'to', 'see'), ('to', 'see', 'if'), ('see', 'if', 'if'), ('if', 'if', 'if'), ('if', 'if', 'this'), ('if', 'this', 'works')]
合并ngrams不同顺序的计数:
>>> from nltk import everygrams
>>> from nltk import FreqDist
>>> corpus = 'testing sentences to see if if if this works'.split()
>>> fd = FreqDist(everygrams(corpus, 1, 3))
>>> fd
FreqDist({('if',): 3, ('if', 'if'): 2, ('to', 'see'): 1, ('sentences', 'to', 'see'): 1, ('if', 'this'): 1, ('to', 'see', 'if'): 1, ('works',): 1, ('testing', 'sentences', 'to'): 1, ('sentences', 'to'): 1, ('sentences',): 1, ...})
或者,,因此您可以这样组合计数器:
>>> from collections import Counter
>>> x = Counter([1,2,3,4,4,5,5,5])
>>> y = Counter([1,1,1,2,2])
>>> x + y
Counter({1: 4, 2: 3, 5: 3, 4: 2, 3: 1})
>>> x
>>> from nltk import FreqDist
>>> FreqDist(['a', 'a', 'b'])
FreqDist({'a': 2, 'b': 1})
>>> a = FreqDist(['a', 'a', 'b'])
>>> b = FreqDist(['b', 'b', 'c', 'd', 'e'])
>>> a + b
FreqDist({'b': 3, 'a': 2, 'c': 1, 'e': 1, 'd': 1})
Alvas 是对的,nltk.everygrams
是完成这项工作的完美工具。但是合并多个迭代器确实没有那么难,也没有那么罕见,所以您应该知道如何去做。关键是任何迭代器都可以转换为列表,但最好只转换一次:
用几个迭代器制作一个列表
就用列表(简单但效率低)
allgrams = list(unigrams) + list(bigrams) + list(trigrams)
或者构建一个列表,正确
allgrams = list(unigrams)
allgrams.extend(bigrams)
allgrams.extend(trigrams)
或使用itertools.chain()
,然后做一个列表
allgrams = list(itertools.chain(unigrams, bigrams, trigrams))
以上产生相同的结果(只要您不尝试重用迭代器 unigrams
等——您需要在示例之间重新定义它们)。
自己使用迭代器
不要与迭代器作对,学会与他们一起工作。许多 Python 函数接受它们而不是列表,为您节省很多 space 和时间。
您可以形成一个迭代器并将其传递给 nltk.FreqDist()
:
fdist = nltk.FreqDist(itertools.chain(unigrams, bigrams, trigrams))
您可以使用多个迭代器。 FreqDist
和 Counter
一样,有一个 update()
方法可以用来递增计数:
fdist = nltk.FreqDist(unigrams)
fdist.update(bigrams)
fdist.update(trigrams)
我正在尝试使用 nltk
中的 ngram
和 freqDist
函数计算各种 ngrams
的频率。
由于 ngram
函数输出是一个 generator
对象,我想在计算频率之前合并每个 ngram 的输出。
但是,我 运行 遇到了合并各种生成器对象的问题。
我已经尝试 itertools.chain
,它创建了一个 itertools
对象,而不是合并生成器。
我终于选择了 permutations
,但之后解析对象似乎是多余的。
到目前为止的工作代码是:
import nltk
from nltk import word_tokenize, pos_tag
from nltk.collocations import *
from itertools import *
from nltk.util import ngrams
import re
corpus = 'testing sentences to see if if if this works'
token = word_tokenize(corpus)
unigrams = ngrams(token,1)
bigrams = ngrams(token,2)
trigrams = ngrams(token,3)
perms = list(permutations([unigrams,bigrams,trigrams]))
fdist = nltk.FreqDist(perms)
for x,y in fdist.items():
for k in x:
for v in k:
words = '_'.join(v)
print words, y
正如您在结果中看到的那样,freq dist 没有正确计算来自各个生成器对象的单词,因为每个生成器对象的频率都是 1。 有没有更 pythonic 的方法来正确地做到这一点?
使用everygrams
,它returns给定范围n的所有n-gram。
>>> from nltk import everygrams
>>> from nltk import FreqDist
>>> corpus = 'testing sentences to see if if if this works'
>>> everygrams(corpus.split(), 1, 3)
<generator object everygrams at 0x7f4e272e9730>
>>> list(everygrams(corpus.split(), 1, 3))
[('testing',), ('sentences',), ('to',), ('see',), ('if',), ('if',), ('if',), ('this',), ('works',), ('testing', 'sentences'), ('sentences', 'to'), ('to', 'see'), ('see', 'if'), ('if', 'if'), ('if', 'if'), ('if', 'this'), ('this', 'works'), ('testing', 'sentences', 'to'), ('sentences', 'to', 'see'), ('to', 'see', 'if'), ('see', 'if', 'if'), ('if', 'if', 'if'), ('if', 'if', 'this'), ('if', 'this', 'works')]
合并ngrams不同顺序的计数:
>>> from nltk import everygrams
>>> from nltk import FreqDist
>>> corpus = 'testing sentences to see if if if this works'.split()
>>> fd = FreqDist(everygrams(corpus, 1, 3))
>>> fd
FreqDist({('if',): 3, ('if', 'if'): 2, ('to', 'see'): 1, ('sentences', 'to', 'see'): 1, ('if', 'this'): 1, ('to', 'see', 'if'): 1, ('works',): 1, ('testing', 'sentences', 'to'): 1, ('sentences', 'to'): 1, ('sentences',): 1, ...})
或者,
>>> from collections import Counter
>>> x = Counter([1,2,3,4,4,5,5,5])
>>> y = Counter([1,1,1,2,2])
>>> x + y
Counter({1: 4, 2: 3, 5: 3, 4: 2, 3: 1})
>>> x
>>> from nltk import FreqDist
>>> FreqDist(['a', 'a', 'b'])
FreqDist({'a': 2, 'b': 1})
>>> a = FreqDist(['a', 'a', 'b'])
>>> b = FreqDist(['b', 'b', 'c', 'd', 'e'])
>>> a + b
FreqDist({'b': 3, 'a': 2, 'c': 1, 'e': 1, 'd': 1})
Alvas 是对的,nltk.everygrams
是完成这项工作的完美工具。但是合并多个迭代器确实没有那么难,也没有那么罕见,所以您应该知道如何去做。关键是任何迭代器都可以转换为列表,但最好只转换一次:
用几个迭代器制作一个列表
就用列表(简单但效率低)
allgrams = list(unigrams) + list(bigrams) + list(trigrams)
或者构建一个列表,正确
allgrams = list(unigrams) allgrams.extend(bigrams) allgrams.extend(trigrams)
或使用
itertools.chain()
,然后做一个列表allgrams = list(itertools.chain(unigrams, bigrams, trigrams))
以上产生相同的结果(只要您不尝试重用迭代器 unigrams
等——您需要在示例之间重新定义它们)。
自己使用迭代器
不要与迭代器作对,学会与他们一起工作。许多 Python 函数接受它们而不是列表,为您节省很多 space 和时间。
您可以形成一个迭代器并将其传递给
nltk.FreqDist()
:fdist = nltk.FreqDist(itertools.chain(unigrams, bigrams, trigrams))
您可以使用多个迭代器。
FreqDist
和Counter
一样,有一个update()
方法可以用来递增计数:fdist = nltk.FreqDist(unigrams) fdist.update(bigrams) fdist.update(trigrams)