【问题标题】:Creating a dictionary for each word in a file and counting the frequency of words that follow it为文件中的每个单词创建字典并计算其后单词的频率
【发布时间】:2017-11-27 12:06:49
【问题描述】:

我正在尝试解决一个难题,但我迷路了。

这是我应该做的:

INPUT: file
OUTPUT: dictionary

Return a dictionary whose keys are all the words in the file (broken by
whitespace). The value for each word is a dictionary containing each word
that can follow the key and a count for the number of times it follows it.

You should lowercase everything.
Use strip and string.punctuation to strip the punctuation from the words.

Example:
>>> #example.txt is a file containing: "The cat chased the dog."
>>> with open('../data/example.txt') as f:
...     word_counts(f)
{'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}

这就是我到目前为止所拥有的一切,至少试图找出正确的单词:

def word_counts(f):
    i = 0
    orgwordlist = f.split()
    for word in orgwordlist:
        if i<len(orgwordlist)-1:
            print orgwordlist[i]
            print orgwordlist[i+1]

with open('../data/example.txt') as f:
    word_counts(f)

我想我需要以某种方式使用 .count 方法并最终将一些字典压缩在一起,但我不确定如何计算每个第一个单词的第二个单词。

我知道我离解决问题还差得很远,但我试着一步一步来。任何帮助表示赞赏,即使只是指向正确方向的提示。

【问题讨论】:

  • f.split()f 是文件处理程序,而不是字符串。

标签: python dictionary nltk counter n-gram


【解决方案1】:

我们可以在两遍中解决这个问题:

  1. 在第一遍中,我们构造一个Counter,并使用zip(..)计算两个连续单词的元组;和
  2. 然后我们将 Counter 转入字典字典。

这会产生以下代码:

from collections import Counter, defaultdict

def word_counts(f):
    st = f.read().lower().split()
    ctr = Counter(zip(st,st[1:]))
    dc = defaultdict(dict)
    for (k1,k2),v in ctr.items():
        dc[k1][k2] = v
    return dict(dc)

【讨论】:

  • Nit:不剥离标点符号。
【解决方案2】:

我们可以一次性完成

  1. 使用defaultdict 作为计数器。
  2. 迭代二元组,就地计数

所以...为简洁起见,我们将省略规范化和清理:

>>> from collections import defaultdict
>>> counter = defaultdict(lambda: defaultdict(int))
>>> s = 'the dog chased the cat'
>>> tokens = s.split()
>>> from itertools import islice
>>> for a, b in zip(tokens, islice(tokens, 1, None)):
...     counter[a][b] += 1
...
>>> counter
defaultdict(<function <lambda> at 0x102078950>, {'the': defaultdict(<class 'int'>, {'cat': 1, 'dog': 1}), 'dog': defaultdict(<class 'int'>, {'chased': 1}), 'chased': defaultdict(<class 'int'>, {'the': 1})})

还有一个更易读的输出:

>>> {k:dict(v) for k,v in counter.items()}
{'the': {'cat': 1, 'dog': 1}, 'dog': {'chased': 1}, 'chased': {'the': 1}}
>>>

【讨论】:

  • the cat chased the dog 是正确的句子:D
【解决方案3】:

首先是一只勇敢的猫追狗!其次,它有点棘手,因为我们不是每天都与这种类型的解析进行交互。代码如下:

k = "The cat chased the dog."
sp = k.split()
res = {}
prev = ''
for w in sp:
    word = w.lower().replace('.', '')
    if prev in res:
        if word.lower() in res[prev]:
            res[prev][word] += 1
        else:
            res[prev][word] = 1
    elif not prev == '':
        res[prev] = {word: 1}
    prev = word
print res

【讨论】:

  • 因为我们不是每天都与这种类型的解析进行交互”。我们不?这是自然语言处理中的基本处理。这称为 2-gram
  • 谢谢!现在我知道了!
  • @WillemVanOnsem aka Bigram
【解决方案4】:

你可以:

  1. 创建剥离词列表;
  2. 使用zip(list_, list_[1:]) 或任何成对迭代的方法创建单词对;
  3. 创建包含第一个单词的字典,然后是第二个单词的列表;
  4. 计算列表中的单词。

像这样:

from collections import Counter
s="The cat chased the dog."
li=[w.lower().strip('.,') for w in s.split()] # list of the words
di={}                                         
for a,b in zip(li,li[1:]):                    # words by pairs
    di.setdefault(a,[]).append(b)             # list of the words following first

di={k:dict(Counter(v)) for k,v in di.items()} # count the words
>>> di
{'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}

如果你有一个文件,只需从文件中读入一个字符串并继续。


你也可以

  1. 前两个步骤相同
  2. 使用defaultdictCounter 作为工厂。

像这样:

from collections import Counter, defaultdict
li=[w.lower().strip('.,') for w in s.split()]
dd=defaultdict(Counter)
for a,b in zip(li, li[1:]):
    dd[a][b]+=1

>>> dict(dd)
{'the': Counter({'dog': 1, 'cat': 1}), 'chased': Counter({'the': 1}), 'cat': Counter({'chased': 1})}

或者,

>>> {k:dict(v) for k,v in dd.items()}   
{'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}

【讨论】:

    【解决方案5】:

    我认为这是一个不导入 defaultdict 的一次性解决方案。它还有标点符号剥离。我已尝试针对大文件或重复打开文件对其进行优化

    from itertools import islice
    
    class defaultdictint(dict):
        def __missing__(self,k):
            r = self[k] = 0
            return r
    
    class defaultdictdict(dict):
        def __missing__(self,k):
            r = self[k] = defaultdictint()
            return r
    
    keep = set('1234567890abcdefghijklmnopqrstuvwxy ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    
    def count_words(file):
        d = defaultdictdict()
        with open(file,"r") as f:
            for line in f:
                line = ''.join(filter(keep.__contains__,line)).strip().lower().split()
                for one,two in zip(line,islice(line,1,None)):
                    d[one][two] += 1
        return d
    
    print (count_words("example.txt"))
    

    将输出:

    {'chased': {'the': 1}, 'cat': {'chased': 1}, 'the': {'dog': 1, 'cat': 1}}
    

    【讨论】:

    • 你没有关闭打开的文件
    • @MatiasCicero 啊我想知道是不是这样,我想现在已经解决了
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2022-07-16
    • 1970-01-01
    相关资源
    最近更新 更多